1. Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm
    Information ausblenden

Keine Ahnung wie ich eine lokale Variable aktualisieren kann und diese im SELECT ausgeben kann

Dieses Thema im Forum "Microsoft SQL Server" wurde erstellt von Christian_T, 12 August 2015.

  1. Christian_T

    Christian_T Benutzer

    Hallo Leute,

    ich bin ein SQL-Rookie und habe folgendes Problem:

    Quell-Tabelle:
    Mitarbeiter | Abwesenheitsgrund | Datum
    Meier | Urlaub | 12.08.2015
    Meier | Urlaub | 13.08.2015
    Meier | Urlaub | 14.08.2015
    Meier | Urlaub | 17.08.2015
    Meier | Krank | 18.08.2015
    Meier | Urlaub | 19.08.2015

    Zum 15. + 16. (Sa und So) gibt es keine Eintragungen, da keine Arbeitstage.

    Ich möchte mit einer Stored Procedure folgende Zieltabelle erhalten, wenn ich die Stored Procedure mit dem heutigen Datum 12.08.2015 aufrufe:
    Mitarbeiter | Abwesenheitsgrund | abwesendBisEinschliesslich
    Meier | Urlaub | 17.08.2015

    Kann mir einer von Euch sagen mit welchen Methoden ich diese Zieltabelle erhalten kann?

    Danke im voraus,
    Christian
     
  2. ukulele

    ukulele Datenbank-Guru

    Das ist "fast" ganz einfach:
    Code:
    /*
    CREATE TABLE test(
       Mitarbeiter VARCHAR(20),
       Abwesenheitsgrund VARCHAR(10),
       Datum DATETIME
       );
    
    INSERT INTO test VALUES ('Meier','Urlaub','2015-12-08 00:00:00.000');
    INSERT INTO test VALUES ('Meier','Urlaub','2015-13-08 00:00:00.000');
    INSERT INTO test VALUES ('Meier','Urlaub','2015-14-08 00:00:00.000');
    INSERT INTO test VALUES ('Meier','Urlaub','2015-17-08 00:00:00.000');
    INSERT INTO test VALUES ('Meier','Urlaub','2015-19-08 00:00:00.000');
    INSERT INTO test VALUES ('Meier','Krank','2015-18-08 00:00:00.000');
    
    SELECT   *
    FROM   test
    */
    WITH t AS (
       SELECT   t1.Datum AS Datum_von,
           t1.Datum AS Datum_bis,
           cast(convert(VARCHAR(10),t1.Datum,104) AS VARCHAR(1000)) AS Pfad,
           0 AS [Level],
           t1.Abwesenheitsgrund,
           t1.Mitarbeiter
       FROM   test t1
       LEFT JOIN test t2
       ON     t1.Datum = (   CASE
                   WHEN   datepart(dw,t2.Datum+1) BETWEEN 1 AND 5
                   THEN   t2.Datum+1
                   WHEN   datepart(dw,t2.Datum+1) = 6
                   THEN   t2.Datum+3
                   WHEN   datepart(dw,t2.Datum+1) = 7
                   THEN   t2.Datum+2
                   END )
       AND     t1.Abwesenheitsgrund = t2.Abwesenheitsgrund
       AND     t1.Mitarbeiter = t2.Mitarbeiter
       WHERE   t2.Datum IS NULL
       UNION ALL
       SELECT   t.Datum_von AS datum_von,
           t3.Datum AS Datum_bis,
           cast(Pfad + '/' + convert(VARCHAR(10),t3.Datum,104) AS VARCHAR(1000)) AS Pfad,
           [Level] + 1 AS [Level],
           t.Abwesenheitsgrund,
           t.Mitarbeiter
       FROM   test t3
       JOIN   t
       ON     t3.Datum = (   CASE
                   WHEN   datepart(dw,t.Datum_bis+1) BETWEEN 1 AND 5
                   THEN   t.Datum_bis+1
                   WHEN   datepart(dw,t.Datum_bis+1) = 6
                   THEN   t.Datum_bis+3
                   WHEN   datepart(dw,t.Datum_bis+1) = 7
                   THEN   t.Datum_bis+2
                   END )
       AND     t3.Abwesenheitsgrund = t.Abwesenheitsgrund
       AND     t3.Mitarbeiter = t.Mitarbeiter
       )
    SELECT   t.Mitarbeiter,
         t.Datum_von,
         t.Datum_bis,
         t.Abwesenheitsgrund,
         t.[Level] + 1 AS Dauer,
         t.Pfad
    FROM   t
    WHERE NOT EXISTS (   SELECT   1
               FROM   t t4
               WHERE   t4.Datum_von = t.Datum_von
               AND     t4.Abwesenheitsgrund = t.Abwesenheitsgrund
               AND     t4.Mitarbeiter = t.Mitarbeiter
               AND     t4.Datum_bis > t.Datum_bis )
    ORDER BY t.Mitarbeiter,t.Datum_von
    OPTION (MAXRECURSION 200)
    
    Ich verwende keine Prozedur sondern baue alles in eine CTE-Abfrage, die sich zusammenhängende Tage nach Mitarbeiter und Abwesenheitsgrund sucht und diese ähnlich einer Baumstruktur mit Unterelementen verkettet. Die Spalten für Pfad und Level sind eigentlich nur zur Veranschaulichung. Die Tage Samstag und Sonntag handle ich in diesem Fall mit einer CASE-Schleife ab um zum nächsten Arbeitstag zu springen. Da ich schon viel zu lange an dem Code geschraubt habe, spare ich mir jetzt mal tiefergehende Ausführungen. Darüber könnte man vermutlich Bücher schreiben und das ist auch für Profis sicherlich nicht einfach, ich grübel da jedes mal drüber.
     
    Zuletzt bearbeitet: 12 August 2015
  3. Christian_T

    Christian_T Benutzer

    @ukulele, recht herzlichen Dank! :)
    Es funktioniert als Stored Procedure bei mir im SQL 2014 Management Studio.
    Ich hätte es natürlcih gerne etwas simpler gehabt. ;-)
     
  4. ukulele

    ukulele Datenbank-Guru

    Ich würde das gar nicht als SP machen, du kannst auch eine View anlegen und darauf dann einfach nach Datum oder nach Mitarbeiter abfragen.
     
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden