Wie macht man: 1 Datensatz mit 3 Tagen Dauer => 3 Datensätze mit 1 Tag Dauer

yatri

Neuer Benutzer
Beiträge
2
Ich brauche dringend und schnell Hilfe bei einer Umwandlung von Datensätzen. Ob dies mit einer Tabellenwertfunktion, einer besonderen gespeicherten Prozedur, o.a. funktioniert ist dabei egal.
Folgendes Problem: Es soll umgewandelt werden (A) zu (B).

(A)
Art Mitarbeiter Start Ende
Urlaub Maier 07.01.2014 00:00 09.01.2014 00:00
Urlaub Schmidt 27.02.2014 00:00 02.03.2014 00:00
krank Herbst 11.01.2014 13:00 13.01.2014 00:00

zu (B)
Art Mitarbeiter Start Ende
Urlaub Maier 07.01.2014 00:00 07.01.2014 00:00
Urlaub Maier 08.01.2014 00:00 08.01.2014 00:00
Urlaub Maier 09.01.2014 00:00 09.01.2014 00:00
Urlaub Schmidt 27.02.2014 00:00 01.03.2014 00:00
Urlaub Schmidt 28.02.2014 00:00 28.02.2014 00:00
Urlaub Schmidt 01.03.2014 00:00 01.03.2014 00:00
Urlaub Schmidt 02.03.2014 00:00 02.03.2014 00:00
krank Herbst 11.01.2014 13:00 13.01.2014 00:00
krank Herbst 11.01.2014 00:00 13.01.2014 00:00
krank Herbst 11.01.2014 00:00 13.01.2014 00:00


Wie erstellen ich also aus einem Eintrag zu 3 Tagen Urlaub die entsprechenden 3 Einträge zu je 1 Tag Urlaub (mit korrektem Datum).

Die Datumsangaben sind datetime-Typen, können aber natürlich im Rahmen einer Sicht o.ä. auch onvertiert werden. Nur die krank-Einträge können eine Uhrzeit enthalten – und dies nur für den Anfangstag. Weitere Spalten zur Auslagerung von Zeit sind natürlich machbar. Ausgewertet wird später in Excel per SVERWEIS, daher werden einzelne Tageseinträge gebraucht. (Neben den Urlaubs- und Krank-Einträgen existieren sehr viele Tageseinträge für Arbeit oder auch Überstundenabbau ..)
Falls dies in NICHT möglich ist mit SQL, aber jemandem eine Lösung in Access oder Excel einfällt, in der die SQL-Daten ausgewertet werden, wäre das Problem auch gelöst.
Bitte sendet auch halbfertige Antworten, da die Zeit so drängt.
 
Werbung:
Bitte sendet auch halbfertige Antworten, da die Zeit so drängt.

Hätte eine Lösung in SQL, aber PostgreSQL, ginge das auch?

Du hast:

Code:
test=*# select * from yatri ;
  art  |  ma  |  dauer
--------+--------+-----------------------------------------------
 urlaub | maier  | ["2014-01-07 00:00:00","2014-01-14 00:00:00")
 krank  | herbst | ["2014-01-11 13:00:00","2014-01-13 00:00:00")
(2 rows)

Ich erstelle mir, damit es einfacher wird, einen VIEW mit den Tagen im Januar:
Code:
create view januar as select tsrange(s.a, s.a+'1day'::interval, '[)') from (select * from generate_series('2014-01-01'::timestamp, '2014-01-31'::timestamp, '1day'))s(a);

Dieser enthält:

Code:
test=*# select * from januar ;
  tsrange
-----------------------------------------------
 ["2014-01-01 00:00:00","2014-01-02 00:00:00")
 ["2014-01-02 00:00:00","2014-01-03 00:00:00")
 ["2014-01-03 00:00:00","2014-01-04 00:00:00")
 ["2014-01-04 00:00:00","2014-01-05 00:00:00")
 ["2014-01-05 00:00:00","2014-01-06 00:00:00")
 ["2014-01-06 00:00:00","2014-01-07 00:00:00")
 ["2014-01-07 00:00:00","2014-01-08 00:00:00")
 ["2014-01-08 00:00:00","2014-01-09 00:00:00")
 ["2014-01-09 00:00:00","2014-01-10 00:00:00")
 ["2014-01-10 00:00:00","2014-01-11 00:00:00")
 ["2014-01-11 00:00:00","2014-01-12 00:00:00")
 ["2014-01-12 00:00:00","2014-01-13 00:00:00")
 ["2014-01-13 00:00:00","2014-01-14 00:00:00")
 ["2014-01-14 00:00:00","2014-01-15 00:00:00")
 ["2014-01-15 00:00:00","2014-01-16 00:00:00")
 ["2014-01-16 00:00:00","2014-01-17 00:00:00")
 ["2014-01-17 00:00:00","2014-01-18 00:00:00")
 ["2014-01-18 00:00:00","2014-01-19 00:00:00")
 ["2014-01-19 00:00:00","2014-01-20 00:00:00")
 ["2014-01-20 00:00:00","2014-01-21 00:00:00")
 ["2014-01-21 00:00:00","2014-01-22 00:00:00")
 ["2014-01-22 00:00:00","2014-01-23 00:00:00")
 ["2014-01-23 00:00:00","2014-01-24 00:00:00")
 ["2014-01-24 00:00:00","2014-01-25 00:00:00")
 ["2014-01-25 00:00:00","2014-01-26 00:00:00")
 ["2014-01-26 00:00:00","2014-01-27 00:00:00")
 ["2014-01-27 00:00:00","2014-01-28 00:00:00")
 ["2014-01-28 00:00:00","2014-01-29 00:00:00")
 ["2014-01-29 00:00:00","2014-01-30 00:00:00")
 ["2014-01-30 00:00:00","2014-01-31 00:00:00")
 ["2014-01-31 00:00:00","2014-02-01 00:00:00")
(31 rows)

Nun das magische SQL:
Code:
test=*# select art, ma, yatri.dauer * januar.tsrange from yatri , januar where not isempty(yatri.dauer * januar.tsrange) order by ma, art, tsrange;
  art  |  ma  |  ?column?
--------+--------+-----------------------------------------------
 krank  | herbst | ["2014-01-11 13:00:00","2014-01-12 00:00:00")
 krank  | herbst | ["2014-01-12 00:00:00","2014-01-13 00:00:00")
 urlaub | maier  | ["2014-01-07 00:00:00","2014-01-08 00:00:00")
 urlaub | maier  | ["2014-01-08 00:00:00","2014-01-09 00:00:00")
 urlaub | maier  | ["2014-01-09 00:00:00","2014-01-10 00:00:00")
 urlaub | maier  | ["2014-01-10 00:00:00","2014-01-11 00:00:00")
 urlaub | maier  | ["2014-01-11 00:00:00","2014-01-12 00:00:00")
 urlaub | maier  | ["2014-01-12 00:00:00","2014-01-13 00:00:00")
 urlaub | maier  | ["2014-01-13 00:00:00","2014-01-14 00:00:00")
(9 rows)

Benötigt PostgreSQL ab Version 9.2 (RANGE-Typen, hier TSRANGE)

Doku:
* http://www.postgresql.org/docs/9.3/interactive/rangetypes.html
* http://www.postgresql.org/docs/9.3/interactive/functions-range.html
 
SCHÖN, vielen Dank für deine Idee und Antwort. ABER: Du schreibst: "Hätte eine Lösung in SQL, aber PostgreSQL, ginge das auch?" - doch deine Lösung ist in PostgresSQL, oder? Da ich mich mit tsrange nicht auskenne und mir Google-Suchen sagen, dass dies ein reiner PostgresSQL-Befehl ist, frage ich dich, ob deine Lösung mit MS-SQL geht. Und nochmals : vielen Dank, dass du so schnell geantwortest hast.
 
SCHÖN, vielen Dank für deine Idee und Antwort. ABER: Du schreibst: "Hätte eine Lösung in SQL, aber PostgreSQL, ginge das auch?" - doch deine Lösung ist in PostgresSQL, oder? Da ich mich mit tsrange nicht auskenne und mir Google-Suchen sagen, dass dies ein reiner PostgresSQL-Befehl ist, frage ich dich, ob deine Lösung mit MS-SQL geht. Und nochmals : vielen Dank, dass du so schnell geantwortest hast.

Soweit mir bekannt, unterstützt keine andere Datenbank außer PostgreSQL RANGE-Typen. Es geht sicher auch anders, aber ich kenne PG halt etwas und Lösungen fallen mir halt mit PG als System und seinen Features ein.
 
Werbung:
Für MS SQL könnte man sich eine Funktion schreiben die ähnlich wie die eingebauten range() Funktionen in PG arbeiten. Hier mal ein Beispiel (auf die Schnelle da ich grade erst aus dem Urlaub komme): http://www.mssqltips.com/sqlservertip/2800/sql-server-function-to-return-a-range-of-dates/

Ich würde ein Script empfehlen das zu jedem Eintrag der Originaltabelle die entsprechenden Zeiträume in eine Hilfstabelle schreibt. Falls es nicht zu langsam wird kann man auch die Funktionen wie oben beschrieben in einer Sicht aufrufen.
 
Zurück
Oben