【问题标题】:SQL multiple date from single column to multiple columnSQL从单列到多列的多个日期
【发布时间】:2012-11-28 22:03:16
【问题描述】:

如何移动如下所示的日期列。

User              Date
====              ====
001               2012/12/01 09:00
001               2012/12/01 11:00
001               2012/12/01 12:00
001               2012/12/01 13:00
001..             ...        

并如下列出它们。

User  date         time1   time2   time3  time4    time5  
001   2012/12/01   09:00   11:00   12:00  13:00    14:00   

感谢 Bluefeet 的解决方案。我测试了脚本,得到了以下结果。

2   2012/11/04  09:00:00.000    NULL    NULL    NULL    NULL    NULL    NULL
2   2012/11/08  NULL    09:00:00.000    18:00:00.000    NULL    NULL    NULL    NULL
2   2012/11/09  NULL    NULL    NULL    09:00:00.000    18:00:00.000    NULL    NULL
2   2012/11/10  NULL    NULL    NULL    NULL    NULL    09:00:00.000    18:00:00.000

时间似乎跳到下一个日期同一用户的最后一个空列?有没有办法让我从第一列开始为同一用户安排下一个日期的顺序?

【问题讨论】:

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


    【解决方案1】:

    您没有指定您使用的是什么 RDBMS,但您之前使用 sql server 标记标记了问题,所以我假设那是数据库。

    您可以使用 SQL Server 中的PIVOT 函数执行此操作。有两种方法可以做到这一点,一种是对所有值进行硬编码的静态方法,另一种是在运行时确定值的动态方法。

    静态枢轴:

    select *
    from 
    (
      select [user], convert(varchar(10), date, 111) date,
        right(convert(varchar(50), date, 121), 12) time
        , 'time'+cast(row_number() over(partition by [user], convert(varchar(10), date, 111) order by date) as varchar(10)) rn
      from yourtable
    ) src
    pivot
    (
      max(time)
      for rn in (time1, time2, time3, time4)
    ) piv
    

    SQL Fiddle with Demo

    动态枢轴:

    DECLARE @cols AS NVARCHAR(MAX),
        @query  AS NVARCHAR(MAX)
    
    select @cols = STUFF((SELECT distinct ',' + QUOTENAME('time'+cast(row_number() over(partition by [user], convert(varchar(10), date, 111) order by date) as varchar(10))) 
                        from yourtable
                FOR XML PATH(''), TYPE
                ).value('.', 'NVARCHAR(MAX)') 
            ,1,1,'')
    
    set @query = 'SELECT [user], date,' + @cols + ' from 
                 (
                    select [user], convert(varchar(10), date, 111) date,
                      right(convert(varchar(50), date, 121), 12) time
                      , ''time''+cast(row_number() over(partition by [user], convert(varchar(10), date, 111) order by date) as varchar(10)) rn
                    from yourtable
                ) x
                pivot 
                (
                    max(time)
                    for rn in (' + @cols + ')
                ) p '
    
    execute(@query)
    

    SQL Fiddle with Demo

    聚合/CASE 版本:

    如果由于某种原因您不想使用PIVOT 函数,那么您也可以使用带有CASE 语句的聚合函数。

    select [user], date,
      max(case when rn = 1 then time end) Time1,
      max(case when rn = 2 then time end) Time2,
      max(case when rn = 3 then time end) Time3,
      max(case when rn = 4 then time end) Time4
    from
    (
      select [user], convert(varchar(10), date, 111) date,
        right(convert(varchar(50), date, 121), 12) time
        , row_number() over(partition by [user], convert(varchar(10), date, 111) order by date)) rn
      from yourtable
    ) src
    group by [user], date
    

    SQL Fiddle with Demo

    所有三个产生相同的结果:

    | USER |       DATE |        TIME1 |        TIME2 |        TIME3 |        TIME4 |
    ---------------------------------------------------------------------------------
    |  001 | 2012/12/01 | 09:00:00.000 | 11:00:00.000 | 12:00:00.000 | 13:00:00.000 |
    |  001 | 2012/12/02 | 09:00:00.000 | 11:00:00.000 | 12:00:00.000 | 13:00:00.000 |
    

    【讨论】:

    • 谢谢。是的,我使用的是 SQL 2008
    • @user1833676 查看我的编辑,我必须将用户和日期值都更改为 row_number()partition by
    • 太好了!!.. 谢谢!.
    猜你喜欢
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    • 2015-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    • 2015-10-23
    相关资源
    最近更新 更多