2016-08-24 4 views
0

Ich habe eine Abfrage, dass es jede Stunde zählt, mit einer Pivot-Tabelle. Wie wäre es möglich, alle 30 Minuten zu zählen?Wie wird jede halbe Stunde gezählt?

zum Beispiel 8: 00-8: 29,8: 30-8: 59,9: 00-9: 29 usw. bis 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) 

Ich benutze SQL Server 2012 (Version Microsoft SQL Server Management Studio 11.0.3128.0)

Antwort

1

Versuchen Sie es mit iif wie folgt:

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 wird nicht richtig verwendet –

1

Um Zählungen von Tag und die halbe Stunde, so etwas wie dies funktionieren sollte.

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; 

Das Formatieren des Ergebnisses könnte später erfolgen.

1

Sie brauchen ein paar Dinge, und dann fällt diese Abfrage einfach zusammen.

Erstens, vorausgesetzt, Sie benötigen mehrere Daten, werden Sie wollen, was als Calendar Table (Hands-down, wahrscheinlich die nützlichste Analysetabelle) bekannt ist.

Als nächstes wirst du entweder eine vorhandene Numbers Tabelle wollen, wenn Sie eine haben, oder erzeugen nur die erste on the fly:

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

(rekursive CTE - erzeugt eine Tabelle mit einer Liste von Zahlen beginnend bei 0).

Diese beiden Tabellen bieten die Grundlage für eine Bereichsabfrage basierend auf den Zeitstempeln in Ihrer Haupttabelle. Dadurch wird es für den Optimierer sehr einfach, Bucket-Zeilen für jede Aggregation, die Sie gerade ausführen, zu erstellen. Das durch CROSS JOIN Sie die zwei Tabellen zusammen in einer Unterabfrage gemacht wird, sowie das Hinzufügen ein paar andere abgeleitete Spalten:

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 

(beachten Sie, dass, wenn der Datumsbereich ausreichend groß ist, kann es vorteilhaft sein, zu speichern Dies ist eine temporäre Tabelle mit Indizes. Bei kleinen Tabellen und Datasets ist die Leistungssteigerung wahrscheinlich nicht spürbar.

Jetzt, da wir unsere Bereiche haben, ist es trivial, unsere Gruppen zu erhalten und die Tabelle zu drehen.
Oh, und SQL Server hat einen spezifischen Operator für 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 

Der Schwenk soll die immer einzelnen Spalten kümmern, und COUNT automatisch null Zeilen lösen. Sollte alles sein, was Sie brauchen.

Verwandte Themen