Aus tätglichen Zeitstempeln einen Zeitraum definieren

Zocker-3001

Neuer Benutzer
Beiträge
2
Hallo zusammen,

ich habe das Problem das unsere Stechuhr alle Zeiten einzeln auflistet ohne einen Anfang / Endzeitpunkt

Ich möchte gerne anhand einer Spalte den Anfang und Endzeitpunkt mittels Select herrausfinden.
Beispiel:

Name | Art | Datum
Mustermann A | Urlaub | 05.04.2018
Mustermann A | Urlaub | 06.04.2018
Mustermann A | Urlaub | 16.04.2018
Mustermann A | Urlaub | 17.04.2018
Mustermann A | Urlaub | 18.04.2018

Ziel wäre mittels Select diese Liste:

Name | Art | Anfangsdatum | Enddatum
Mustermann A | Urlaub | 05.04.2018 | 06.04.2018
Mustermann A | Urlaub | 16.04.2018 | 18.04.2018

Ich bekomme diese Konstellation bisher nur mittels Countbefehl herraus doch bei diesem Szenario wo 2 Urlaubszeiträume in einem Monat auftauchen, komm ich grad nicht mehr klar.

Ich würde mich über eure hilfe freuen :)
 
Werbung:
Mögliche Lösung wäre eine stored proc, die über die Tabelle geht und dabei die Zeiträume zusammenfaßt.

Alternativ das bei Eintragen via TRIGGER machen: wenn der neue Datensatz als Urlaub ersichtlich ist, der sich dem Vortag anschließt, den bestehenden Datensatz entsprechend erweitern (also gleich von-bis führen und bis auf den neuen Datumswert aktualisieren)
 
Geht auch einfacher ;-)

Code:
andreas@[local]:5432/test*# select * from urlaub ;
 wer |  datum   
-----+------------
  1 | 2018-03-01
  1 | 2018-03-02
  1 | 2018-03-03
  1 | 2018-03-04
  1 | 2018-03-14
  1 | 2018-03-15
  1 | 2018-03-16
  1 | 2018-03-26
  1 | 2018-03-27
  1 | 2018-03-28
  2 | 2018-04-01
  2 | 2018-04-02
  2 | 2018-04-03
  2 | 2018-04-04
  2 | 2018-04-05
  2 | 2018-04-15
  2 | 2018-04-16
  2 | 2018-04-17
  2 | 2018-04-18
(19 rows)

andreas@[local]:5432/test*# with start as (select *, row_number() over (order by start) from (select u1.wer as w1, u1.datum as start, u2.wer as w2 from urlaub u1 left join urlaub u2 on u1.wer=u2.wer and u1.datum = u2.datum + '1day'::interval) foo where w2 is null), ende as (select *, row_number() over (order by ende) from (select u1.wer as w1, u1.datum as ende, u2.wer as w2 from urlaub u1 left join urlaub u2 on u1.wer=u2.wer and u1.datum = u2.datum - '1day'::interval) foo where w2 is null) select * from start inner join ende on start.row_number = ende.row_number and start.w1=ende.w1;
 w1 |  start  | w2 | row_number | w1 |  ende  | w2 | row_number
----+------------+----+------------+----+------------+----+------------
  1 | 2018-03-01 |  |  1 |  1 | 2018-03-04 |  |  1
  1 | 2018-03-14 |  |  2 |  1 | 2018-03-16 |  |  2
  1 | 2018-03-26 |  |  3 |  1 | 2018-03-28 |  |  3
  2 | 2018-04-01 |  |  4 |  2 | 2018-04-05 |  |  4
  2 | 2018-04-15 |  |  5 |  2 | 2018-04-18 |  |  5
(5 rows)

andreas@[local]:5432/test*#

Überflüssige Spalten zu entfernen überlasse ich zur Übung ;-)
 
Werbung:
Es ginge auch ohne ROW_NUMBER(), aber natürlich werden Wochenenden und Feiertage, wenn sie nicht als Urlaub eingetragen sind, den Urlaub unterbrechen.
Code:
WITH t(name,art,anfang,ende) AS (
   SELECT   t1.name,
       t1.art,
       t1.datum,
       t1.datum
   FROM   tabelle t1
   LEFT JOIN tabelle t2
   ON     t1.name = t2.name
   AND     t1.art = t2.art
   AND     t1.datum = dateadd(day,1,t2.datum)
   WHERE   t2.datum IS NULL
   UNION ALL
   SELECT   t.name,
       t.art,
       t.anfang,
       t3.datum
   FROM   t
   INNER JOIN tabelle t3
   ON     t.name = t3.name
   AND     t.art = t3.art
   AND     t.ende = dateadd(day,-1,t3.datum)
   )
SELECT   t.name,
     t.art,
     t.anfang,
     max(t.ende) AS ende
FROM   t
 
Zurück
Oben