在Sql查询中将行转换为列

时间:2014-10-12 01:31:50

标签: sql sql-server sql-server-2008 pivot

我很难弄清楚这一点请帮助我 我有时间进/出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

所以无论谁签入或结账,然后记录将按顺序显示结果,如果有人应该退房,但意外按下按钮,那么这将显示为(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

我尝试使用pivot

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

任何人都可以解释如何将行转换为我已经花了很多天的列。

1 个答案:

答案 0 :(得分: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)