1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen
  2. Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, Oracle, Sql-Server, Postgres, Access uvm
    Information ausblenden

Query mit Datumsbereichen

Dieses Thema im Forum "Microsoft SQL Server" wurde erstellt von haemi, 29 November 2017.

  1. haemi

    haemi Benutzer

    Hallo,

    Ich habe folgendes Szenario:

    - eine Tabelle mit Patientendaten
    - eine Tabelle Bewegungsdaten der Patienten

    Auf Grundlage beider Tabellen sollte ich anhand des ersten Datumseintrages eines jeden Patienten in einem drei Monatszyklus Daten zusammenfassen können.

    Beispiel:

    Patient Name
    4711 Meier
    8810 Müller

    Patient Datum Position Wert ID
    8810 15.01.17 02.0200 35 1
    8810 20.02.17 02.0200 50 2
    8810 20.04.17 02.0200 20 3
    4711 10.01.17 02.0200 15 4
    4711 15.08.17 02.0200 55 5

    Das Resultat sollte ungefähr so aussehen:

    Patient Datumsbereich Wert
    8810 15.01.17 - 14.04.17 85
    8810 15.04.17 - 14.07.17 20
    4711 10.01.17 - 09.04.17 15
    4711 10.04.17 - 09.07.17 0
    4711 10.07.17 - 09.10.17 55

    Ich habe diverse Ansätze getestet (Cursor, Fetch...).

    Hat hier jemand eine Idee?

    Besten Dank im Voraus.
    Hämi
     
  2. akretschmer

    akretschmer Datenbank-Guru

    Mal als Ansatz...

    Code:
    test=# select * from haemi ;
     patient |  datum  | position  | wert | id
    ---------+------------+-----------+------+----
      8810 | 2017-01-15 | '02.0200' |  35 |  1
      8810 | 2017-02-20 | '02.0200' |  50 |  2
      8810 | 2017-04-17 | '02.0200' |  20 |  3
      4711 | 2017-01-10 | '02.0200' |  15 |  4
      4711 | 2017-08-15 | '02.0200' |  55 |  5
    (5 rows)
    
    test=# with tmp as (select patient, min(datum), max(datum), extract(month from age(max(datum),min(datum)))::int / 3 + 1 as c
    from haemi group by patient) select patient, min + (g-1) * '1month'::interval as start, min + g * '1month'::interval as ende from tmp left join lateral (select * from generate_series(1,tmp.c) g) x on (true);
     patient |  start  |  ende   
    ---------+---------------------+---------------------
      8810 | 2017-01-15 00:00:00 | 2017-02-15 00:00:00
      8810 | 2017-02-15 00:00:00 | 2017-03-15 00:00:00
      4711 | 2017-01-10 00:00:00 | 2017-02-10 00:00:00
      4711 | 2017-02-10 00:00:00 | 2017-03-10 00:00:00
      4711 | 2017-03-10 00:00:00 | 2017-04-10 00:00:00
    (5 rows)
    
    Erste Abfrage ist Deine Tabelle, die zweite Abfrage liefert jetzt schon mal die geforderten Zeitbereiche. Das kannst Du nun wieder mit der originalen Tabelle über die Zeitbereiche joinen, um daraus dann Deine gewünschte Aggregation zu machen.

    Ich mache da jetzt nicht weiter, weil ich PostgreSQL nutze und viele der Features in anderen Datenbanken wie wohl auch in Deiner nicht zur Verfügung stehen.

    Wenn ich weitermachen würde, würde ich start und ende erst einmal zu einer DATERANGE verbinden, macht den Rest dann einfacher. Ich hoffe, der Weg ist halbwegs verständlich, aber Dinge wie genertae_series() und wohl erst besonders den LATERAL JOIN wirst Du nicht haben. DATERANGE auch nicht.
     
  3. akretschmer

    akretschmer Datenbank-Guru

    ich seh grad, ich hab dann bei der Ausgabe mit 1 Monat gearbeitet, korrekt wäre gewesen:

    Code:
    test=# with tmp as (select patient, min(datum), max(datum), extract(month from age(max(datum),min(datum)))::int / 3 + 1 as c
    from haemi group by patient) select patient, min + (g-1) * '3month'::interval as start, min + g * '3month'::interval as ende from tmp left join lateral (select * from generate_series(1,tmp.c) g) x on (true);
     patient |  start  |  ende   
    ---------+---------------------+---------------------
      8810 | 2017-01-15 00:00:00 | 2017-04-15 00:00:00
      8810 | 2017-04-15 00:00:00 | 2017-07-15 00:00:00
      4711 | 2017-01-10 00:00:00 | 2017-04-10 00:00:00
      4711 | 2017-04-10 00:00:00 | 2017-07-10 00:00:00
      4711 | 2017-07-10 00:00:00 | 2017-10-10 00:00:00
    (5 rows)
    
    test=#
    
     
  4. haemi

    haemi Benutzer

    Hallo

    Vielen Dank für die rasche Antwort. Ich benutze MS SQL 2014 .

    Dein Ansatz tönt interessant - nur leider habe ich keine "generate_series" in MS SQL.

    Mein Ansatz sieht folgendermassen aus:

    USE
    VWORK

    TRUNCATE Table PatCockpit

    DECLARE
    @BL_PATNR int,
    @vStartDate date,
    @vEndDate date=getDate(),
    @vFinishDate date,
    @vSumZeitReal smallint

    DECLARE C CURSOR FOR SELECT DISTINCT BL_PATNR
    FROM VMW
    WHERE BL_POSNR='02.0200'
    ORDER BY BL_PATNR
    OPEN C

    FETCH NEXT FROM C INTO @BL_PATNR

    WHILE @@FETCH_STATUS= 0 BEGIN
    -- Search first entry
    SELECT TOP 1
    @vStartDate=BL_DATUM
    FROM VMW
    WHERE BL_POSNR = '02.0200' and BL_PATNR = @BL_PATNR
    GROUP BY BL_DATUM

    -- Date range and calculation
    WHILE @vStartDate < Dateadd(month,+3,@vEndDate)
    BEGIN
    SET @vFinishDate = Dateadd(month,+3,@vStartDate)
    SELECT
    @vSumZeitReal = SUM(BL_ZEITREAL)
    FROM VMW
    WHERE BL_POSNR = '02.0200' and BL_PATNR=@BL_PATNR and BL_DATUM BETWEEN @vStartDate and @vFinishDate
    IF @vSumZeitReal is not NULL
    INSERT INTO PatCockpit (PatNr,StartDate,EndDate,TimeReal,ServiceGroup) VALUES(@BL_PATNR,@vStartDate,@vFinishDate,@vSumZeitReal,9)

    SET @vStartDate = Dateadd(month,+3,@vStartDate)
    END
    FETCH NEXT FROM C INTO @BL_PATNR
    END

    CLOSE C
    DEALLOCATE C

    Dies läuft soweit. Bei der grossen Datenmenge (>25'000 Patienten bzw. > 10 Mio. Bewegungsdaten) ist die Abfrage einfach zu langsam.

    Andere Ideen?

    Danke.
     
  5. akretschmer

    akretschmer Datenbank-Guru


    *shrug*

    DB wechseln?

    Wie Du siehst, kann PG solche Dinge ohne großes rumgemache mit vielen Schleifen und so in einem Einzeiler handeln. Und mal ehrlich: 10 Millionen Rows ist ja eher peanuts. Unsere Kunden, die "große" Datenmengen haben, haben teilweise 2-stellige Milliarden von Rows pro Table.
     
  6. haemi

    haemi Benutzer

    DB wechseln wäre gut ;). Dürfen aber "nur" MS SQL benutzen.

    Zu den Datenmengen
    Ja sind nur Peanuts. Die Positionstabelle habe ich in meiner Abfrage noch nicht drin (im Beispiel 02.0200). Sind ebenfalls über 1'000 Einträge. In Relation Patienten, Positionen und Bewegungsdaten wird dies eine "grössere" Matrix ergeben. Hinzu kommt noch, dass bei den Positionen Zeit- und Wertlimiten bestehen. Diese werden schlussendlich auch berücksichtigt.

    Übrigens: Das Gesamte läuft auf ein Patienten Cockpit hin.

    Danke.
     
  7. akretschmer

    akretschmer Datenbank-Guru

    Why? Datenbanken ohne Lizenzkosten sind per se nicht gut?
     
  8. haemi

    haemi Benutzer

    Vorgabe "Nur Microsoft" Produkte. Egal was (Office, Webserver....).
     
  9. akretschmer

    akretschmer Datenbank-Guru

    Kündigungsgrund!
     
    Kampfgummibaerlie gefällt das.
  10. haemi

    haemi Benutzer

    Ist ein Kunde....
     
  11. haemi

    haemi Benutzer

    Würde der Chef keine Freude an mir haben....
     
  12. Kampfgummibaerlie

    Kampfgummibaerlie Datenbank-Guru

    Kenne mich mit Access überhaupt nicht aus, sollte aber mittels Excel (was du ja angeblich nutzen darfst, da ein Office-Programm), einfach über Tabellenübergreifende "Verknüpfungen" machbar sein.
     
Die Seite wird geladen...

Diese Seite empfehlen