【问题标题】:SQL Server Pivot with Date Ranges as Columns以日期范围为列的 SQL Server Pivot
【发布时间】:2014-03-18 14:49:02
【问题描述】:

我有一个表格,其结构如下,记录员工到达和分散时间:

我希望在查询/存储过程中实现的是根据附加图像的底部网格在日期范围之间返回数据透视类型数据。

请问您的专业知识或样品如何完成?我一直在研究,但是我所有的努力都没有结果。

【问题讨论】:

  • 每个userid/DateIn 组合都会有多个条目吗?您是在寻找动态解决方案还是会提前知道您的日期?
  • Hello bluefeet 确实每个用户 ID / DateIn 有多个条目 - 日期范围可以由用户选择,所以我假设动态是正确的答案。
  • 如果我可以补充的话,我相信 sql 2000 中没有数据透视函数,这是我死亡的主要原因:P 我目前正在研究交叉表查询解决方案。
  • 您使用的是 SQL Server 2000 吗?
  • 是的,我明白这就是问题所在:(

标签: sql-server pivot pivot-table


【解决方案1】:

您可以使用 PIVOT 函数来获得最终结果,但是由于您正在聚合 string/time 值,因此您还需要使用像 row_number() 这样的窗口函数来为每个 @ 返回多行987654324@/datein组合。

我将使用类似于以下的子查询来为每个 userid/datein 组合返回具有唯一序列号的数据:

select name, 
    datein = convert(varchar(10), datein, 120), 
    dttime = cast(timein as varchar(5)) + ' - '+ cast(timeout as varchar(5)),
    row_number() over(partition by userid, datein order by datein) seq
from dbo.yourtable;

一旦你有了这些数据,你就可以轻松地应用数据透视:

select name, [2013-04-10]
from
(
    select name, 
        datein = convert(varchar(10), datein, 120), 
        dttime = cast(timein as varchar(5)) + ' - '+ cast(timeout as varchar(5)),
        row_number() over(partition by userid, datein order by datein) seq
    from dbo.yourtable
) d
pivot
(
    max(dttime)
    for datein in ([2013-04-10])
) piv;

如果你有未知数量的值,那么你会想要使用动态 SQL:

DECLARE 
    @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX),
    @startdate datetime,
    @enddate datetime,
    @paramdef nvarchar(max)

set @startdate = '2013-02-01'
set @enddate = '2013-05-10';
set @paramdef = '@startdate datetime, @enddate datetime';

select @cols = STUFF((SELECT ',' + QUOTENAME(convert(varchar(10), datein, 120)) 
                    from dbo.yourtable
                    where datein > @startdate
                        and datein <= @enddate
                    group by datein
                    order by datein
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = N'SELECT name, '+ @cols + '
            from 
            (
                select name, 
                    datein = convert(varchar(10), datein, 120), 
                    dttime = cast(timein as varchar(5)) + '' - ''+ cast(timeout as varchar(5)),
                    row_number() over(partition by userid, datein order by datein) seq
                from dbo.yourtable
                where datein > @startdate
                    and datein <= @enddate
            ) x
            pivot 
            (
                max(dttime)
                for datein in ('+@cols+')
            ) p '

exec sp_executesql @query, @paramdef, @startdate = @startdate, @enddate = @enddate;

【讨论】:

  • 纯粹出于好奇。加窗函数 (row_number) 如何消除聚合字符串时会出现的问题?谢谢
  • @Kiril 当您聚合一个字符串/日期或需要使用max/min 的东西时,您最终只会为要分组的每个项目返回一个值。通过在应用分组依据时基于datein/userid 创建唯一序列,您将返回多行数据。
  • 我同时将 db 移至 sql 2005,它运行良好。 bluefeet 感谢您为协助所投入的所有精力和时间。
【解决方案2】:

我会在以下行添加一个 DISTINCT:

select @cols - select @cols = stuff((select DISTINCT ',' + ....

【讨论】:

    猜你喜欢
    • 2021-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-18
    • 1970-01-01
    相关资源
    最近更新 更多