2016-08-24 110 views
0

我有一個查詢,它使用數據透視表每小時計數。 如何能夠每30分鐘計數一次?如何計算每半小時?

例如8:00-8:29,8:30-8:59.9:00-9:29等等,直到5:00

SELECT CONVERT(varchar(8),start_date,1) AS 'Day', 

     SUM(CASE WHEN DATEPART(hour,start_date) = 8 THEN 1 ELSE 0 END) as eight , 

     SUM(CASE WHEN DATEPART(hour,start_date) = 9 THEN 1 ELSE 0 END) AS nine, 
     SUM(CASE WHEN DATEPART(hour,start_date) = 10 THEN 1 ELSE 0 END) AS ten, 
     SUM(CASE WHEN DATEPART(hour,start_date) = 11 THEN 1 ELSE 0 END) AS eleven, 
     SUM(CASE WHEN DATEPART(hour,start_date) = 12 THEN 1 ELSE 0 END) AS twelve, 
     SUM(CASE WHEN DATEPART(hour,start_date) = 13 THEN 1 ELSE 0 END) AS one_clock, 
     SUM(CASE WHEN DATEPART(hour,start_date) = 14 THEN 1 ELSE 0 END) AS two_clock, 
     SUM(CASE WHEN DATEPART(hour,start_date) = 15 THEN 1 ELSE 0 END) AS three_clock, 
     SUM(CASE WHEN DATEPART(hour,start_date) = 16 THEN 1 ELSE 0 END) AS four_clock 

FROM test 
where user_id is not null 
GROUP BY CONVERT(varchar(8),start_date,1) 
ORDER BY CONVERT(varchar(8),start_date,1) 

我使用SQL Server 2012(版本的Microsoft SQL Server Management Studio中11.0.3128.0),如下使用iif

回答

1

嘗試:

SELECT CONVERT(varchar(8),start_date,1) AS 'Day', SUM(iif(DATEPART(hour,start_date) = 8 and 
DATEPART(minute,start_date) >= 0 and 
DATEPART(minute,start_date) =< 29,1,0)) as eight_tirty 
    FROM test where user_id is not null GROUP BY 
CONVERT(varchar(8),start_date,1) ORDER BY 
CONVERT(varchar(8),start_date,1) 
+0

iff使用不正確 –

1

要獲得通過一天半小時計數,這樣的事情應該工作。

SELECT day, half_hour, count(1) AS half_hour_count 
FROM (
    SELECT 
     CAST(start_date AS date) AS day, 
     DATEPART(hh, start_date) 
      + 0.5*(DATEPART(n,start_date)/30) AS half_hour 
    FROM test 
    WHERE user_id IS NOT NULL 
) qry 
GROUP BY day, half_hour 
ORDER BY day, half_hour; 

格式化結果可稍後完成。

1

你需要一些東西,然後這個查詢就在一起。首先,假設你需要多個日期,你會想要知道什麼是Calendar Table(可能是最有用的分析表)。

接下來,你會想要一個現有Numbers表,如果你有一個,或者只是動態生成第一:

WITH Halfs AS (SELECT CAST(0 AS INT) m 
       UNION ALL 
       SELECT m + 1 
       FROM Halfs 
       WHERE m < 24 * 2) 
SELECT m 
FROM Halfs 

(遞歸CTE - 生成與數字列表的表從0開始)。

這兩個表將爲您提供基於主表中的時間戳的範圍查詢的基礎。這將使優化程序非常容易地爲您所做的任何聚合存儲行。這是由CROSS JOIN做了荷蘭國際集團的兩個表一起在一個子查詢,以及添加其他幾個派生列的:

WITH Halfs AS (SELECT CAST(0 AS INT) m 
       UNION ALL 
       SELECT m + 1 
       FROM Halfs 
       WHERE m < 24 * 2) 

SELECT calendarDate, m, rangeStart, rangeEnd 
FROM (SELECT Calendar.calendarDate, Halfs.m rangeGroup, 
      DATEADD(minutes, m * 30, CAST(Calendar.calendarDate AS DATETIME2) rangeStart, 
      DATEADD(minutes, (m + 1) * 30, CAST(Calendar.calendarDate AS DATETIME2) rangeEnd     
     FROM Calendar 
     CROSS JOIN Halfs 
     WHERE Calendar.calendarDate >= CAST('20160823' AS DATE) 
      AND Calendar.calendarDate < CAST('20160830' AS DATE) 
      -- OR whatever your date range actually is. 
    ) Range 
ORDER BY rangeStart 

(注意,如果日期的範圍足夠大,它可能是有益的保存這對於小表和數據集來說,性能增益不太可能是顯而易見的)

既然我們有我們的範圍,那麼獲取我們的組,並旋轉表是微不足道的。
呵呵,SQL Server有一個特定的運算符PIVOTing

WITH Halfs AS (SELECT CAST(0 AS INT) m 
       UNION ALL 
       SELECT m + 1 
       FROM Halfs 
       WHERE m < 3 * 2) 
       -- Intentionally limiting range for example only 

SELECT calendarDate AS day, [0], [1], [2], [3], [4], [5], [6] 
          -- If you're displaying "nice" names, 
          -- do it at this point, or in the reporting application 
FROM (SELECT Range.calendarDate, Range.rangeGroup 
     FROM (SELECT Calendar.calendarDate, Halfs.m rangeGroup, 
        DATEADD(minutes, m * 30, CAST(Calendar.calendarDate AS DATETIME2) rangeStart, 
        DATEADD(minutes, (m + 1) * 30, CAST(Calendar.calendarDate AS DATETIME2) rangeEnd     
        FROM Calendar 
        CROSS JOIN Halfs 
        WHERE Calendar.calendarDate >= CAST('20160823' AS DATE) 
         AND Calendar.calendarDate < CAST('20160830' AS DATE) 
         -- OR whatever your date range actually is. 
        ) Range 
     LEFT JOIN Test 
      ON Test.user_id IS NOT NULL 
       AND Test.start_date >= Range.rangeStart 
       AND Test.start_date < Range.rangeEnd 
    ) AS DataTable 
PIVOT (COUNT(*) 
     FOR Range.rangeGroup IN ([0], [1], [2], [3], [4], [5], [6])) AS PT 
           -- Only covers the first 6 groups, 
           -- or the first three hours. 
ORDER BY day 

樞軸應照顧個人獲得的字段,並且COUNT會自動解決空行。應該是你需要的一切。