Benutzer mit den meisten Antworten
Anzahl Pro Stunde und Tag

Frage
-
Guten Tag
Ich bräuchte wiedermal ein wenig Hilfe.
Ich habe zwei Datenfelder
Eingang = 02.02.2015 08:10:15
Ausgang = 04.02.2015 09:10:20
Nun möchte ich eine Abfrage generieren welche mir folgendes Resultat anzeigt (Anzahl pro Stunde):
Der Hintergrund ist, die Patienten kommen auf einen bestimmten Zeitpunkt und verlassen auf einen bestimmten Zeitpunkt die Abteilung. Nun versuche ich herauszufinden, wieviele Betten sind zu einem bestimmten Zeitabschnitt besetzt, gruppiert nach Tag.
Mein Ansatz war:
sum(case When DATEPART(hour, Eingang) <= 00 AND DATEPART(hour, Ausgang) >=00 THEN 1 ELSE 0 END) as T00
und das für jede Stunde.
Was ich aber nicht hingekriegt habe, wie teile ich das noch auf die Tage auf.
Herzlichen Dank für die Hilfe
Freundliche Grüsse
Walo Beck
- Bearbeitet W_Beck Montag, 30. März 2015 08:12 Fehler korrigiert
Antworten
-
Hallo Walo,
weiter aufteilen kann man es, in dem man den Datumsanteil mit einer Kalendertabelle verknüpft. Ähnliches kann man auch mit den Stunden machen.
Eine angefangene Lösung:
-- eine (partielle) Kalendertabelle CREATE TABLE #Kalender (Datum Date NOT NULL CONSTRAINT PK_Kalender PRIMARY KEY); INSERT INTO #Kalender(Datum) SELECT DATEADD(dd, number, '2015-01-01') FROM master..spt_values WHERE type = 'P'; -- für Stunden (ggf. weiter aufteilen nach Wochentage etc.) CREATE TABLE #Stunden (Stunde int NOT NULL CONSTRAINT PK_Stunde PRIMARY KEY, StundeText varchar(30) CONSTRAINT UK_Stunde_Text UNIQUE); DECLARE @Stunde int = 0; WHILE @Stunde < 24 BEGIN INSERT INTO #Stunden (Stunde, StundeText) VALUES (@Stunde, CAST(@Stunde AS varchar) + ':00-' + CAST(@Stunde + 1 AS varchar) + ':00'); SET @Stunde += 1; END; -- eine Belegung (partiell) CREATE TABLE #Belegung ( BelegungId int NOT NULL, Eingang Datetime2 NOT NULL, Ausgang Datetime2 NOT NULL); INSERT INTO #Belegung VALUES (1, '2015-02-02 08:10:15', '2015-02-04 09:10:20'), (2, '2015-02-03 18:00:15', '2015-02-04 12:15:20'), (3, '2015-02-04 10:00:15', '2015-02-04 15:30:20'); -- liefert alle belegten Stunden SELECT k.Datum, s.Stunde, COUNT(*) FROM #Belegung AS b INNER JOIN #Kalender AS k ON k.Datum >= CAST(b.Eingang AS date) AND k.Datum <= CAST(b.Ausgang AS date) INNER JOIN #Stunden AS s ON (k.Datum = CAST(b.Eingang AS date) AND s.Stunde >= DATEPART(hour, b.Eingang)) OR (k.Datum = CAST(b.Ausgang AS date) AND s.Stunde <= DATEPART(hour, b.Ausgang)) OR (k.Datum > CAST(b.Eingang AS date) AND k.Datum < CAST(b.Ausgang AS date)) GROUP BY k.Datum, s.Stunde ORDER BY k.Datum, s.Stunde; -- erweitert um belegte und nicht belegte via CROSS APPLY SELECT k.Datum, s.Stunde, SUM(s.Belegt) FROM #Belegung AS b INNER JOIN #Kalender AS k ON k.Datum >= CAST(b.Eingang AS date) AND k.Datum <= CAST(b.Ausgang AS date) CROSS APPLY (SELECT Stunde, -- oder StundeText CASE WHEN (k.Datum = CAST(b.Eingang AS date) AND s.Stunde >= DATEPART(hour, b.Eingang)) OR (k.Datum = CAST(b.Ausgang AS date) AND s.Stunde <= DATEPART(hour, b.Ausgang)) OR (k.Datum > CAST(b.Eingang AS date) AND k.Datum < CAST(b.Ausgang AS date)) THEN 1 ELSE 0 END AS Belegt FROM #Stunden AS s) AS s(Stunde, Belegt) GROUP BY k.Datum, s.Stunde ORDER BY k.Datum, s.Stunde;
Den Teil mit PIVOT oder wie Du es gelöst hast über SUM(CASE...) habe ich mir vorerst geschenkt.
Gruß Elmar
- Bearbeitet Elmar Boye Montag, 30. März 2015 09:25
- Als Antwort markiert W_Beck Dienstag, 31. März 2015 11:30
Alle Antworten
-
Hallo Walo,
um die Frage sinnvoll beantworten zu können, benötigen wir ein kleines Repro-Skript.
Darin sollten das DDL für die Tabelle und die Inserts für die Beispiele, sowie das gewünschte Ergebnis enthalten sein.Wie man sich eine Hilfstabelle für die Stunden über die Tage aufbaut, hatten wir gerade erst letzte Woche im forum:
https://social.msdn.microsoft.com/Forums/sqlserver/de-DE/6efe9b72-ba7a-41d9-b85d-fd551eba0792/print-ausgabe-einer-variable-bergeben?forum=sqlserverDarüber könnte ich mir einen Join mit den Patientendaten vorstellen und dann eine entsprechende Auswertung.
Einen schönen Tag noch,
Christoph
--
Microsoft SQL Server MVP - http://www.insidesql.org/blogs/cmu -
Hallo Walo,
weiter aufteilen kann man es, in dem man den Datumsanteil mit einer Kalendertabelle verknüpft. Ähnliches kann man auch mit den Stunden machen.
Eine angefangene Lösung:
-- eine (partielle) Kalendertabelle CREATE TABLE #Kalender (Datum Date NOT NULL CONSTRAINT PK_Kalender PRIMARY KEY); INSERT INTO #Kalender(Datum) SELECT DATEADD(dd, number, '2015-01-01') FROM master..spt_values WHERE type = 'P'; -- für Stunden (ggf. weiter aufteilen nach Wochentage etc.) CREATE TABLE #Stunden (Stunde int NOT NULL CONSTRAINT PK_Stunde PRIMARY KEY, StundeText varchar(30) CONSTRAINT UK_Stunde_Text UNIQUE); DECLARE @Stunde int = 0; WHILE @Stunde < 24 BEGIN INSERT INTO #Stunden (Stunde, StundeText) VALUES (@Stunde, CAST(@Stunde AS varchar) + ':00-' + CAST(@Stunde + 1 AS varchar) + ':00'); SET @Stunde += 1; END; -- eine Belegung (partiell) CREATE TABLE #Belegung ( BelegungId int NOT NULL, Eingang Datetime2 NOT NULL, Ausgang Datetime2 NOT NULL); INSERT INTO #Belegung VALUES (1, '2015-02-02 08:10:15', '2015-02-04 09:10:20'), (2, '2015-02-03 18:00:15', '2015-02-04 12:15:20'), (3, '2015-02-04 10:00:15', '2015-02-04 15:30:20'); -- liefert alle belegten Stunden SELECT k.Datum, s.Stunde, COUNT(*) FROM #Belegung AS b INNER JOIN #Kalender AS k ON k.Datum >= CAST(b.Eingang AS date) AND k.Datum <= CAST(b.Ausgang AS date) INNER JOIN #Stunden AS s ON (k.Datum = CAST(b.Eingang AS date) AND s.Stunde >= DATEPART(hour, b.Eingang)) OR (k.Datum = CAST(b.Ausgang AS date) AND s.Stunde <= DATEPART(hour, b.Ausgang)) OR (k.Datum > CAST(b.Eingang AS date) AND k.Datum < CAST(b.Ausgang AS date)) GROUP BY k.Datum, s.Stunde ORDER BY k.Datum, s.Stunde; -- erweitert um belegte und nicht belegte via CROSS APPLY SELECT k.Datum, s.Stunde, SUM(s.Belegt) FROM #Belegung AS b INNER JOIN #Kalender AS k ON k.Datum >= CAST(b.Eingang AS date) AND k.Datum <= CAST(b.Ausgang AS date) CROSS APPLY (SELECT Stunde, -- oder StundeText CASE WHEN (k.Datum = CAST(b.Eingang AS date) AND s.Stunde >= DATEPART(hour, b.Eingang)) OR (k.Datum = CAST(b.Ausgang AS date) AND s.Stunde <= DATEPART(hour, b.Ausgang)) OR (k.Datum > CAST(b.Eingang AS date) AND k.Datum < CAST(b.Ausgang AS date)) THEN 1 ELSE 0 END AS Belegt FROM #Stunden AS s) AS s(Stunde, Belegt) GROUP BY k.Datum, s.Stunde ORDER BY k.Datum, s.Stunde;
Den Teil mit PIVOT oder wie Du es gelöst hast über SUM(CASE...) habe ich mir vorerst geschenkt.
Gruß Elmar
- Bearbeitet Elmar Boye Montag, 30. März 2015 09:25
- Als Antwort markiert W_Beck Dienstag, 31. März 2015 11:30