【问题标题】:Dynamic SQL Procedure with Pivot displaying counts based on Date Range带有基于日期范围显示计数的 Pivot 动态 SQL 过程
【发布时间】:2017-11-18 03:16:29
【问题描述】:

我有一个包含多个用户条目的表。 我想根据传递给存储过程的日期范围提取用户条目数。

开始日期:2017 年 11 月 9 日 结束日期:2017 年 11 月 11 日

但是,响应需要根据日期范围内的天数进行动态响应。

这是一种所需的格式:

【问题讨论】:

  • 表的图片通常远不如 ascii 表示有用,因为它们很难粘贴到 sqlfiddle.com 的“文本到 DDL”工具中以快速模拟测试表。请考虑不要将数据图像放在 SQL 问题中 - 人们可能会开始给出他们查询编辑器的屏幕截图的答案!
  • 造成你困难的部分是什么?
  • 丹,我只需要知道如何做到这一点的语法。
  • 有人有想法吗?:)
  • 您使用的是哪个DBMS 产品?后格雷斯?甲骨文? “SQL”只是一种查询语言,并不是特定数据库产品的名称。

标签: sql pivot procedure


【解决方案1】:

既然您已经提供了示例,我已经更新了我的答案,它根据您提供的数据为您提供了解决方案。

请注意,您可以更改日期范围,查询也会相应更新。

请记住,此 SQL 查询适用于 SQL Server:

create table #tbl1 (
    [UserId] int
    ,[UserName] nvarchar(max)
    ,[EntryDateTime] datetime
);

insert into #tbl1 ([UserId],[UserName],[EntryDateTime])
values
    (1,'John Doe','20171109')
    ,(1,'John Doe','20171109')
    ,(1,'John Doe','20171110')
    ,(1,'John Doe','20171111')
    ,(2,'Mike Smith','20171109')
    ,(2,'Mike Smith','20171110')
    ,(2,'Mike Smith','20171110')
    ,(2,'Mike Smith','20171110')
;

-- declare variables
declare
    @p1 date
    ,@p2 date
    ,@diff int
    ,@counter1 int
    ,@counter2 int
    ,@dynamicSQL nvarchar(max)
;

-- set variables
set @p1 = '20171109';   -- ENTER THE START DATE IN THE FORMAT YYYYMMDD
set @p2 = '20171111';   -- ENTER THE END DATE IN THE FORMAT YYYYMMDD
set @diff = datediff(dd,@p1,@p2); -- used to calculate the difference in days
set @counter1 = 0;  -- first counter to be used in while loop
set @counter2 = 0;  -- second counter to be used in while loop
set @dynamicSQL = 'select pivotTable.[UserId] ,pivotTable.[UserName] as [Name] '; -- start of the dynamic SQL statement

-- to get the dates into the query in a dynamic way, you need to do a while loop (or use a cursor)
while (@counter1 < @diff)
begin
    set @dynamicSQL += ',pivotTable.[' + convert(nvarchar(10),dateadd(dd,@counter1,@p1),120) + '] '

    set @counter1 = (@counter1 +1)
end

-- continuation of the dynamic SQL statement
set @dynamicSQL += ' from (
    select
        t.[UserId]
        ,t.[UserName]
        ,cast(t.[EntryDateTime] as date) as [EntryDate]
        ,count(t.[UserId]) as [UserCount]
    from #tbl1 as t
    where
        t.[EntryDateTime] >= ''' + convert(nvarchar(10),@p1,120) + ''' ' +
        ' and t.[EntryDateTime] <= ''' + convert(nvarchar(10),@p2,120) + ''' ' +
    'group by
        t.[UserId]
        ,t.[UserName]
        ,t.[EntryDateTime]
    ) as mainQuery

    pivot (
        sum(mainQuery.[UserCount]) for mainQuery.[EntryDate]
            in ('
;

-- the second while loop which is used to create the columns in the pivot table
while (@counter2 < @diff)
begin
    set @dynamicSQL += ',[' + convert(nvarchar(10),dateadd(dd,@counter2,@p1),120) + ']'

    set @counter2 = (@counter2 +1)
end

-- continuation of the SQL statement
set @dynamicSQL += ')
    ) as pivotTable'
;

-- this is the easiet way I could think of to get rid of the leading comma in the query
set @dynamicSQL = replace(@dynamicSQL,'in (,','in (');

print @dynamicSQL   -- included this so that you can see the SQL statement that is generated

exec sp_executesql @dynamicSQL; -- this will run the generate dynamic SQL statement

drop table #tbl1;

让我知道这是否是您要找的。​​p>

【讨论】:

  • 感谢 Lolo4 这是一个正确的解决方案,因为它是动态的。
【解决方案2】:

如果您使用的是 MySQL,这将满足您的需求:

SELECT  UserID,
        UserName,
        SUM(Date = '2017-11-09') '2017-11-09',
        SUM(Date = '2017-11-10') '2017-11-10',
        SUM(Date = '2017-11-11') '2017-11-11'
FROM src
GROUP BY UserID

【讨论】:

    【解决方案3】:

    如果您使用的是 SQL Server,可以尝试使用 PIVOT:

    SELECT *
    FROM
    (SELECT userID, userName, EntryDateTime
     FROM t) src
    PIVOT
    (COUNT(userID)
     FOR EntryDateTime IN (['2017-11-09'], ['2017-11-10'], ['2017-11-11'])) pvt
    

    【讨论】:

      猜你喜欢
      • 2019-05-11
      • 1970-01-01
      • 2021-08-16
      • 1970-01-01
      • 1970-01-01
      • 2014-06-03
      • 1970-01-01
      • 1970-01-01
      • 2021-07-05
      相关资源
      最近更新 更多