2010-09-01 207 views
1

考慮下面的表和行列:轉換行允許重複

上市A.

ID, name, event, type 
1, 'John Doe', '2010-09-01 15:00:00.000', 'input' 
1, 'John Doe', '2010-09-03 11:00:00.000', 'input' 
1, 'John Doe', '2010-09-04 17:00:00.000', 'input' 
1, 'John Doe', '2010-09-02 15:00:00.000', 'output' 
1, 'John Doe', '2010-09-03 16:00:00.000', 'output' 
1, 'John Doe', '2010-09-06 17:00:00.000', 'output' 

我想要的是將行轉換成列,所以我可以有兩個不同的列,輸入事件並輸出事件。像:

上市B.

ID, name, input event, output event 
1, 'John Doe', '2010-09-01 15:00:00.000', '2010-09-02 15:00:00.000' 
1, 'John Doe', '2010-09-03 11:00:00.000', '2010-09-03 16:00:00.000' 
1, 'John Doe', '2010-09-04 17:00:00.000', '2010-09-06 17:00:00.000' 

我能得到類似如下:

清單C.

ID, name, input event, output event 
1, 'John Doe', '2010-09-01 15:00:00.000', null 
1, 'John Doe', '2010-09-03 11:00:00.000', null 
1, 'John Doe', '2010-09-04 17:00:00.000', null 
1, 'John Doe', null, '2010-09-02 15:00:00.000' 
1, 'John Doe', null, '2010-09-03 16:00:00.000' 
1, 'John Doe', null, '2010-09-06 17:00:00.000' 

,但問題是如何平行,因爲重複元組的ID-name是相關的。要轉換行到列我通常這樣的代碼的東西:

select ID, name, max(case when type = 'input' then event else null end) as 'input event', max(case when type = 'output' then event else null end) as 'output event' from events group by ID, name 

,但當然,本集團將要離開了重複,這就是我不想要什麼。

任何想法如何實現與查詢?

這將是一個便攜式SQL解決方案或postgresql,但任何想法非常感謝,很高興。

編輯:抱歉,遲到的答案。 AlexRednic和Mark Ba​​nnister的解決方案都能達到我想要的效果。我終於選擇了第二個,因爲它對我來說更加清晰。謝謝你的回答!

+0

您還沒有表示如何將輸入和輸出事件聯繫起來。 ID和名稱本身不會這樣做,因爲每個類型有三個相同的ID和名稱的事件。從提供的數據中,ID,姓名和時間的組合可以唯一地識別每種類型的單個事件,但是單憑這一點對於無數代表性數據集是可靠的,還是可能存在多個輸出事件天)爲一個單一的ID,姓名和時間? – 2010-09-01 12:47:43

+0

對於任何輸入事件,只能有一個輸出事件,輸出事件的日期總是比輸入事件更早。另外,輸入事件之後總會有輸出事件。不能有兩個連續的輸入事件。我的錯,所提供的數據集不符合這一點。我會糾正它。 – Gothmog 2010-09-01 17:36:37

+0

更清晰,謝謝! – 2010-09-02 09:56:41

回答

2

嘗試以下操作:

select ID, name, event as 'input event', 
     (select min(o.event) 
     from events o 
     where o.type = 'output' and 
       i.ID = o.ID and 
       i.name = o.name and 
       i.event < o.event) as 'output event' 
from events i 
where i.type = 'input' 
group by ID, name, event 
0

我從一開始就寫着:

create table #a(
ID int, 
name varchar(30), 
event datetime, 
type varchar(10) 
) 

insert #a 
select 
1, 'John Doe', '2010-09-01 15:00:00.000', 'input' 
union select 1, 'John Doe', '2010-09-01 16:00:00.000', 'input' 
union select 1, 'John Doe', '2010-09-01 17:00:00.000', 'input' 
union select 1, 'John Doe', '2010-09-02 15:00:00.000', 'output' 
union select 1, 'John Doe', '2010-09-02 16:00:00.000', 'output' 
union select 1, 'John Doe', '2010-09-02 17:00:00.000', 'output' 

- 這裏是解決方案SQL

select 
    ID, 
    name, 
    case when type = 'input' then event else null end "input event", 
    case when type = 'output' then event else null end "output event" 
from #a 
+0

我走到了這一步,但這不是我想要的。我想要獲得的結果只有三行。列表B. – Gothmog 2010-09-01 17:28:33

+0

好的我看到了,但列表B沒有有效的groupin邏輯。你能否說通常「把相同的日期排成一行」?如果你說是,它的正確,我會正確的SQL? – 2010-09-02 07:16:22

1
select t1.id,t1.name,t1.event,t2.event from test t1 
    inner join test t2 on t1.event <= t2.event 
     and t1.type = 'input' 
     and t2.type = 'output' 
        and t1.id = t2.id 
        and t1.name = t2.name 

是你需要以某種方式輸入鏈接的事/輸出會話。在這個查詢中,我通過使用時間戳事件列來完成它。如果這不是你想要的,你能提供更多的信息嗎?

更新:現在,到後處理了一下,你可以做

with a as 
(
select t1.id,t1.name,t1.event as in_event,t2.event as out_event from test t1 
    inner join test t2 on t1.event <= t2.event 
        and t1.type = 'input' 
        and t2.type = 'output' 
        and t1.id = t2.id 
        and t1.name = t2.name 
) 
select id,name,in_event,min(out_event) 
     from a 
group by id,name,in_event 
+0

這將返回0行,因爲輸入事件與輸出事件在不同的日期(但同時) - 輸入發生在第一個輸出上,輸出發生在第二個輸出上。如果輸入/輸出的日期與示例中所表示的日期相同,則 – 2010-09-01 12:42:41

+0

工作。這就是我所說的,我需要更多關於這兩個事件如何鏈接的信息。它是event.input <= event.output?來自Gothmog的響應中的 – AlexRednic 2010-09-02 10:28:50

+0

,event.input 2010-09-02 10:47:00