2014-10-12 38 views
0

我有困難的時候弄清楚這個請幫我 我有時間進/出SQL查詢 我有一張表,如下所示。有四列顯示時間輸入/輸出信息,如...將行轉換爲Sql查詢中的列

Date Day Day TimeStamp CheckType 
10/11/2014 Sat 8:30 am in 
10/11/2014 Sat 11:30am out 
10/11/2014 Sat 1:30pm  in 
10/11/2014 Sat    out 
10/12/2014 Sun 9:00am  in 
10/12/2014 Sun 11:20pm out 
10/12/2014 Sun 5:20pm  out 
10/13/2014 Mon 8:00am  in 
10/13/2014 Mon 6:10pm  in 

所以誰簽入或簽退,則記錄會按順序顯示的結果,如果有人應該看看,但在按鈕按下意外再這將顯示,因爲它是(在),或者如果有人忘記檢查那麼空間會顯示空白

我想行轉換成列,並顯示這些信息在下面

Date  Day Time Type Time Type Time Type Time Type etc----- 
10/11/2014 Sat 8:30am in 11:30am out 1:30pm in  
10/12/2014 Sun 9:00am in 11:20am out 1:20pm in 6:20pm in 
10/13/2014 Mon 8:00am in 6:10pm out 
10/14/2014 Tus 8:20am in 
etc 

我曾嘗試使用樞軸

select Date, Day, [1],[2],[3],[4],[5],[6],[7],[8],[9],[10] etc--- 
from 
(
select Date, Day, Stamptime, CheckTime, userID 
from a table 
) 
pivot 
(
    max(StampTime) 
    for stamptime in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10] etc---) 
) as PivotTable 

任何人都可以解釋如何將行轉換爲我已經花了很多天的列。

+0

SQL小提琴:HTTP:/ /sqlfiddle.com/#!6/0174d(在原始表上有一些優化) – JohnLBevan 2014-10-12 02:02:42

+0

你不能這樣做(在數據庫中;在用戶界面是好的)。問題是有一天您可能會有一次入住,第二天您可能會有兩次入住和一次退房。這意味着第一天所需的列數不同於第二天所需的列數。這也意味着你不知道你需要的最大列數。您可以通過輸出到XML而不是表格數據來解決它,但實際上我認爲您正在爲自己創造痛苦/應該重新評估解決問題的方法。 – JohnLBevan 2014-10-12 02:16:36

回答

2

這裏的東西接近你所追求的,利用XML來獲得可變數量的列。正如我在上面的評論中提到的,我不推薦這種方法。 SQL小提琴:http://sqlfiddle.com/#!3/e5b325/2

select [Date] 
, [Day] 
, (
    select [TimeStamp] [Time] 
    , [CheckType] [Type] 
    from aTable b 
    where b.[Date] = a.[Date] 
    order by [TimeStamp], [CheckType] 
    for xml path ('') 
) CheckInAndOutInfo 
from aTable a 
group by [Date], [Day] 
order by [Date] 

輸出:

DATE  DAY CHECKINANDOUTINFO 
2014-10-11 Sat <Type>Out</Type><Time>08:30:00</Time><Type>In</Type><Time>11:30:00</Time><Type>Out</Type><Time>13:30:00</Time><Type>In</Type> 
2014-10-12 Sun <Time>09:00:00</Time><Type>In</Type><Time>17:20:00</Time><Type>Out</Type><Time>23:20:00</Time><Type>Out</Type> 
2014-10-13 Mon <Time>08:00:00</Time><Type>In</Type><Time>18:10:00</Time><Type>In</Type> 

或者,如果你能保證你永遠不會有超過一定數量簽入更多/每天出局,你可以做以下(這是假設不超過每天5以上): SQL小提琴:http://sqlfiddle.com/#!3/e5b325/4

select * 
from 
(
    select [Date], [Day] 
    , 'T' + CAST(ROW_NUMBER() over (partition by [Date] order by [TimeStamp], [CheckType]) as nvarchar) r 
    , cast([TimeStamp] as nvarchar) pvtVal 
    from aTable 
    where [TimeStamp] is not null 


    union all 

    select [Date], [Day] 
    , 'C' + CAST(ROW_NUMBER() over (partition by [Date] order by [TimeStamp], [CheckType]) as nvarchar) r 
    , cast([CheckType] as nvarchar) pvtVal 
    from aTable 
    where [TimeStamp] is not null 
) x 
pivot 
(
    min(pvtVal) 
    for r in ([T1], [C1], [T2], [C2], [T3], [C3], [T4], [C4], [T5], [C5]) 
) y 
order by [Date] 

輸出:

DATE  DAY T1    C1 T2    C2 T3    C3  T4  C4  T5  C5 
2014-10-11 Sat 08:30:00.0000000 In 11:30:00.0000000 Out 13:30:00.0000000 In  (null) (null) (null) (null) 
2014-10-12 Sun 09:00:00.0000000 In 17:20:00.0000000 Out 23:20:00.0000000 Out  (null) (null) (null) (null) 
2014-10-13 Mon 08:00:00.0000000 In 18:10:00.0000000 In (null)   (null) (null) (null) (null) (null) 

...或者,如果你想使用動態SQL,你可以這樣做: SQL小提琴:http://sqlfiddle.com/#!3/e5b325/6

declare @sql nvarchar(max) 
select @sql = coalesce(@sql+',','') + QUOTENAME('T' + CAST(x as nvarchar)) + ',' + QUOTENAME('C' + CAST(x as nvarchar)) 
from 
(
    select distinct row_number() over (partition by [Date] order by [Date]) x 
    from aTable 
    where [TimeStamp] is not null 
) y 
order by x 

set @sql = 
    'select * 
    from 
    (
     select [Date], [Day] 
     , ''T'' + CAST(ROW_NUMBER() over (partition by [Date] order by [TimeStamp], [CheckType]) as nvarchar) r 
     , cast([TimeStamp] as nvarchar) pvtVal 
     from aTable 
     where [TimeStamp] is not null 

     union all 

     select [Date], [Day] 
     , ''C'' + CAST(ROW_NUMBER() over (partition by [Date] order by [TimeStamp], [CheckType]) as nvarchar) r 
     , cast([CheckType] as nvarchar) pvtVal 
     from aTable 
     where [TimeStamp] is not null 
    ) x 
    pivot 
    (
     min(pvtVal) 
     for r in (' + @sql + ') 
    ) y 
    order by [Date]' 

exec (@sql) 

輸出:

DATE  DAY T1    C1 T2    C2 T3    C3 
2014-10-11 Sat 08:30:00.0000000 In 11:30:00.0000000 Out 13:30:00.0000000 In 
2014-10-12 Sun 09:00:00.0000000 In 17:20:00.0000000 Out 23:20:00.0000000 Out 
2014-10-13 Mon 08:00:00.0000000 In 18:10:00.0000000 In (null)   (null) 
+0

太棒了!非常感謝你的選擇2非常棒。你是男人。但是,我一直在嘗試實現選項3,但我一直在收到一個錯誤,說137信息,級別15,狀態2,行20 必須聲明標量變量「@DomainId」。 消息137,級別15,狀態2,行44 必須聲明標量變量「@DomainId」。 – Steve 2014-10-15 17:55:04

+0

嘿,別擔心。在我的腳本中沒有提及'@ DomainId';所以我認爲你已經修改了腳本並將該值放在了某處。要麼你需要一個聲明語句(類似於'declare @DomainId bigint = 123'),或者你聲明瞭你的變量,然後試圖在動態SQL中使用它;在這種情況下,您需要查看'sp_executesql'(而不是'exec'),將其作爲參數傳遞; http://msdn.microsoft.com/en-gb/library/ms188001.aspx。如果您遇到問題,請使用代碼在SO上搜索或提出新問題。 – JohnLBevan 2014-10-16 16:23:28