SQL Server转置查询结果

时间:2016-11-22 06:26:01

标签: sql-server pivot transpose

我有一张包含以下数据的表格:

ItemId  PendingTime
1       2016-11-23 15:57:56.000
2       2016-07-09 17:33:09.000
3       2015-11-27 18:34:03.000

依旧......

我想知道自过去30分钟,过去1小时,过去1周,过去1个月和过去一年以来待定项目的总和。我提出了以下问题:

SELECT
    SUM(CASE 
           WHEN datediff(MINUTE, PENDING_TIME,GETDATE()) <= 30 
              THEN 1 ELSE 0 
        END) AS '30 Min',
Sum(case when (datediff(MINUTE,PENDING_TIME, GETDATE())) > 30 AND (datediff(MINUTE,PENDING_TIME, GETDATE())) <= 60 then 1 Else 0 End) as 'Over 30 Min',
Sum(case when (datediff(MINUTE,PENDING_TIME, GETDATE())) > 60 AND (datediff(HOUR,PENDING_TIME, GETDATE())) <= 24 then 1 Else 0 End) as 'Over 1 Hr',
Sum(case when (datediff(DAY,PENDING_TIME, GETDATE())) > 1 AND (datediff(DAY,PENDING_TIME, GETDATE())) < 30 then 1 Else 0 End) as '1 month',
Sum(case when datediff(DAY,PENDING_TIME, GETDATE()) >= 30 then 1 Else 0 End) as 'More than month'
from ItemsTable where datepart(yyyy,PENDING_TIME) = DATEPART(yyyy,GETDATE())

这将数据返回为:

30 Min      Over 30 Min Over 1 Hr   1 month     More than month
----------- ----------- ----------- ----------- ---------------
100          350        NULL        NULL        NULL

我希望结果为2列格式:

30 Min       ------     45
Over 30      ------    100
Over 1 hr    ------    null
Over 1 month ------    null

我知道pivot函数,但是我选择的列实际上并不在我选择的表中,而是由于聚合函数而创建的。

如何以2列和多行格式获取此内容。

感谢您的阅读。

2 个答案:

答案 0 :(得分:2)

您可以创建派生列,将等待分类为不同的类型,然后按该列分组:

With waitCodes As (
    Select Case
         When DateDiff(Minute, PENDING_TIME, GetDate()) <= 30 Then '30 Min'
         When DateDiff(Minute, PENDING_TIME, GetDate()) <= 60 Then 'Over 30'
         When DateDiff(Minute, PENDING_TIME, GetDate()) <= 1440 Then 'Over 1 hr'
         When DateDiff(Minute, PENDING_TIME, GetDate()) <= 43200 Then '1 month'
         Else 'More than a month' End As [WaitTime]
      From ItemsTable
      Where DatePart(yyyy, PENDING_TIME) = DatePart(yyyy,GetDate()))
Select [WaitTime], Count(*) As n
  From waitCodes
  Group By [WaitTime];

此外,我强烈建议您更改查询中的Where子句,以便它不会将函数应用于PENDING_TIME列。 There are multiple benefits of this.

...
Where PENDING_TIME >= Convert(date, Convert(char(4), DatePart(yyyy, GetDate()))+'-01-01 00:00:00.000', 121)
  And PENDING_TIME < Convert(date, Convert(char(4), DatePart(yyyy, GetDate())+1)+'-01-01 00:00:00.000', 121)
....

答案 1 :(得分:0)

你可以像每个orignal sql一样使用交叉申请语句

    SELECT c.* FROM 
    (
        SELECT
           SUM(CASE 
               WHEN datediff(MINUTE, PENDING_TIME,GETDATE()) <= 30 
                  THEN 1 ELSE 0 
            END) AS '30 Min',
          Sum(case when (datediff(MINUTE,PENDING_TIME, GETDATE())) > 30 AND (datediff(MINUTE,PENDING_TIME, GETDATE())) <= 60 then 1 Else 0 End) as 'Over 30 Min',
          Sum(case when (datediff(MINUTE,PENDING_TIME, GETDATE())) > 60 AND (datediff(HOUR,PENDING_TIME, GETDATE())) <= 24 then 1 Else 0 End) as 'Over 1 Hr',
          Sum(case when (datediff(DAY,PENDING_TIME, GETDATE())) > 1 AND (datediff(DAY,PENDING_TIME, GETDATE())) < 30 then 1 Else 0 End) as '1 month',
          Sum(case when datediff(DAY,PENDING_TIME, GETDATE()) >= 30 then 1 Else 0 End) as 'More than month'
        from ItemsTable where datepart(yyyy,PENDING_TIME) = DATEPART(yyyy,GETDATE())
    )
    CROSS APPLY(VALUES('30 MIN',a),('Over 30',b),('Over 1 hr',c),('Over 1 month',d),('More than month',e)) c(title,[value])

结果:

title           value
--------------- -----------
30 MIN          100
Over 30         350
Over 1 hr       NULL
Over 1 month    NULL
More than month NULL