2016-11-22 4 views
0

У меня есть таблица со следующими данными:SQL Server транспонировать результат запроса

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 

Я сознаю но столбцы, которые я выбрал, на самом деле не находятся в таблице, которую я выбираю, а они создаются в результате функции агрегата.

Как получить это в формате с двумя столбцами и несколькими строками.

Спасибо, что прочитали.

ответ

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 в запросе, так что Безразлично» t примените функцию к столбцу 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) 
.... 
+0

хорошее решение. BTW, альтернативное предложение WHERE будет работать только в том случае, если соответствующая таблица не имеет будущих дат. – wdosanjos

+0

@wdosanjos Отличная точка. Я предположил, что эта ситуация не может произойти, но это может быть опасным предположением. Я отредактировал предложенный 'WHERE' соответственно. – mendosi

+1

BTW, посмотрите [здесь] (http://stackoverflow.com/questions/13437362/how-to-get-first-and-last-date-of-current-year) для решения о том, как получить первый и последний дни года без строковых манипуляций. 'Где PENDING_TIME> = DATEADD (yy, DATEDIFF (yy, 0, getdate()), 0) и PENDING_TIME wdosanjos

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