SQL Datensatz einfügen

winscheil

Aktiver Benutzer
Beiträge
26
Hallo,

ich habe folgende Ausgangslage:
Arbeitszeiten nach Kalenderwochen unterteilt.
Bsp.:
KW JAHR STUNDEN AUFTRAG
42 2024 60 XYZ
43 2024 65 XYZ
45 2024 55 XYZ
46 2024 70 XYZ
48 2024 60 XYZ
...

Wie ihr sehen könnt, fehlen die Zeiten der KW 44 und KW 47.
Hier sind keine Zeiten aufgelaufen, darum habe ich dazu keinen Datensatz.
In einem Balkendiagramm sollen diese beiden fehlenden KWs schon erscheinen.
Somit brächte ich Datensätze für die fehlenden KWs.
Bsp.:
KW JAHR STUNDEN AUFTRAG
42 2024 60 XYZ
43 2024 65 XYZ
44 2024 0 XYZ
45 2024 55 XYZ
46 2024 70 XYZ
47 2024 0 XYZ
48 2024 60 XYZ

Wie kann ich diese fehlenden KWs hinzufügen?
Der SQL ist aktuell ungefähr so:
select KW, JAHR, SUM(STUNDEN) as STUNDEN, AUFTRAG from QUELLE
group by KW, JAHR, AUFTRAG
 
Werbung:
Hallo.
ich weiss ja nicht wie du die Daten in die Tabelle kriegst, aber genau aus diesem Grund würde ich es vermeiden Daten anzulegen die möglicherweise nachträglich dann doch auftauchen.
Versuche die fehlenden Daten mit einer Hilfstabelle zu füllen und NULL-Werte mit 0 zu ersetzen.
Ist zwar ein wenig aufwendiger aber IMHO dafür korrekt.

Du brauchst eine Hilfstabelle mit dem Jahr und den Kalenderwochen vom Start- bis zum Enddatum und verknüpfst die anschließend mit mittels Left oder right Outerjoin mit deiner Quelltabelle über JAHR und KW . Bei Stunden hast du nachher ein coalesce(sum(stunden), 0) as STUNDEN
Schöne Grüße
 
@MDDaniel hat grundsätzlich Recht, es geht mit einer Hilfstabelle. Schön ist es, eine solche Tabelle dynamisch zu erzeugen. Das kann aber recht tricky werden, hier mal eine Möglichkeit für dein simples Beispiel:
Code:
WITH zeitreihe AS (
    SELECT    min(KW) AS KW,
            JAHR,
            dateadd(week,min(KW),dateadd(year,JAHR-1900,0)) AS erster_Tag,
            dateadd(day,7,dateadd(week,min(KW),dateadd(year,JAHR-1900,0))) AS letzter_Tag
    FROM    quelle
    WHERE    JAHR = ( SELECT min(JAHR) FROM quelle )
    GROUP BY JAHR
    UNION ALL
    SELECT    datepart(week,dateadd(day,7,erster_Tag)),
            datepart(year,dateadd(day,7,erster_Tag)),
            dateadd(day,7,erster_Tag),
            dateadd(day,7,letzter_Tag)
    FROM    zeitreihe
    WHERE    dateadd(day,7,erster_Tag) <= convert(DATE,getdate())
    )
SELECT    zeitreihe.KW,
        zeitreihe.JAHR,
        sum(quelle.STUNDEN) AS STUNDEN,
        quelle.AUFTRAG
FROM    zeitreihe
LEFT JOIN quelle
ON        zeitreihe.KW = quelle.KW
AND        zeitreihe.JAHR = quelle.JAHR
GROUP BY zeitreihe.KW,zeitreihe.JAHR,quelle.AUFTRAG

Es gibt eventuell ein paar Probleme:

- Mit WITH wird on-the-fly eine Tabelle geschaffen. In diesem Fall geht das per Rekursion. Er sucht den niedrigsten Eintrag KW/JAHR aus quelle und addiert so lange 7 Tage, bis der erste Tag der Woche in der Zukunft liegt. Rekursion ist aber (sicherheitshalber) limitiert. Wenn also dein Zeitraum sehr groß wird kann das zu Problemen führen - die aber natürlich lösbar sind. Mit steigender Komplexität kann aber auch Performance ein Problem werden - muss aber nicht.

- Das Ergebnis von datepart(week,DATUM) sowie der erste Tag der Woche hängen von den Ländereinstellungen des Servers ab. In den US beginnt die Woche mit Sonntag und solche Späße. Das ist nicht unbedingt ein Problem, man muss das aber im Hinterkopf haben.

- Es gibt unterschiedliche Zählweisen bei der KW. In DE ist die letzte KW des Jahres 2024 auch die erste KW des Jahres 2025. Wenn man Diagramme machen will sollte das ein Datensatz sein wie in meinem Beispiel der Fall, das kann aber verwirren. Auch WHERE-Filter z.B. auf Zeiten aus dem Jahr 2025 würde dann den ersten Datensatz als 2024 KW 53 anzeigen, aber nur Zeiten aus dem 2025-Teil auch aggregieren.

- Eventuell willst du noch irgendwas auf Mitarbeiter aufteilen. Eventuell sogar mit unterschiedlichen Anfangsdaten für die Statistik, das geht alles. Da muss man dann mehrere Datensätze für den Beginn der Zeitreihe definieren.
 
Werbung:
PS: Eventuell brauchst du auch pro Auftrag einen Startdatensatz für deine Zeitreihe. Dann würde es auch Sinn machen, das Ende eines jeden Auftrags per max() zu ermitteln, hier mal eine etwas andere Vorgehensweise:
Code:
WITH anfangende AS (
    SELECT    min(dateadd(week,KW,dateadd(year,JAHR-1900,0))) AS erster_Tag,
            max(dateadd(week,KW,dateadd(year,JAHR-1900,0))) AS letzter_Tag,
            AUFTRAG
    FROM    quelle
    GROUP BY AUFTRAG
    ), zeitreihe AS (
    SELECT    AUFTRAG,
            datepart(week,erster_Tag) AS KW,
            datepart(year,erster_Tag) AS JAHR,
            erster_Tag,
            letzter_Tag
    FROM    anfangende
    UNION ALL
    SELECT    AUFTRAG,
            datepart(week,dateadd(day,7,erster_Tag)),
            datepart(year,dateadd(day,7,erster_Tag)),
            dateadd(day,7,erster_Tag),
            letzter_Tag
    FROM    zeitreihe
    WHERE    dateadd(day,7,erster_Tag) <= letzter_Tag
    )
SELECT    zeitreihe.KW,
        zeitreihe.JAHR,
        sum(quelle.STUNDEN) AS STUNDEN,
        zeitreihe.AUFTRAG
FROM    zeitreihe
LEFT JOIN quelle
ON        zeitreihe.KW = quelle.KW
AND        zeitreihe.JAHR = quelle.JAHR
GROUP BY zeitreihe.KW,zeitreihe.JAHR,zeitreihe.AUFTRAG
ORDER BY zeitreihe.AUFTRAG,zeitreihe.JAHR,zeitreihe.KW
 
Zurück
Oben