thejoker2305
Goto Top

T SQL Tabelle Updaten Vortagesdatum aus einer anderen Zeile entnehmen

Hallo zusammen,

nach vielen Monaten des Mitlesens und Findens von Lösungen, hier meine erste Frage, bei der ich irgendwie auf der Stelle trete:


Ich habe eine einfache Tabelle:

Mitarbeiter Datum_von Datum_bis
Müller 2015-01-01 NULL
Müller 2015-03-05 NULL
Müller 2015-05-20 NULL

Da diese Tabelle täglich befüllt wird und dabei das Feld Datum_bis immer auf null gesetzt wird, muss ich eine Update-Abfrage erstellen, die folgendes bewirkt:

- das Feld Datum_bis soll mit einem Datum gefüllt werden, welches dem Vortag des nächsthöheren Datums des gleichen Mitarbeiters entspricht.
- wenn es sich um die Zeile mit dem maximalen Datum des Mitarbeiters handelt, soll weiterhin NULL drin stehen bleiben.

also so:

Mitarbeiter Datum_von Datum_bis
Müller 2015-01-01 2015-03-04
Müller 2015-03-05 2015-05-19
Müller 2015-05-20 NULL

Meine erste Idee wäre hier über einen Cursor alle Zeilen nach 'Mitarbeiter und gültig_ab' absteigend sortiert zu durchlaufen:

während des Durchlaufens je Zeile
- Mitarbeiter und gültig_ab in eine Variable zwischenspeichern @mitarbeiter, @datum_von
- nächste Zeile prüfen, ob gleicher Mitarbeiter (@Mitarbeiter), wenn ja, dann Update Tabelle set datum_bis = @datum_von - 1 Tag

aktuell bin ich mit dem Skript soweit:

DECLARE @Datum_von date 
DECLARE @Mitarbeiter varchar

DECLARE cursor_ma_von CURSOR FOR
  SELECT Mitarbeiter, Datum_von FROM [Datenbank].[dbo].[Mitarbeitertabelle] ORDER BY Mitarbeiter, Datum_von DESC FOR UPDATE OF datum_von
open cursor_ma_von
 FETCH NEXT FROM cursor_ma_von 
 INTO @Mitarbeiter, @Datum_von

 WHILE (@@FETCH_STATUS = 0)  
 BEGIN
	UPDATE[Datenbank].[dbo].[Mitarbeitertabelle]
	SET Datum_bis = DATEADD(DAY,-1,@Datum_von) 
	WHERE Mitarbeiter = @Mitarbeiter AND @Datum_von <> Datum_von AND CURRENT OF cursor_ma_von 
	
	FETCH NEXT FROM cursor_ma_von 
        INTO @Mitarbeiter, @Datum_von
	
 END

 CLOSE cursor_ma_von
 DEALLOCATE cursor_ma_von

Aktuell erhalte ich die Fehlermeldung

Msg 156, Level 15, State 1, Line 14
Incorrect syntax near the keyword 'CURRENT'.

Scheinbar kann ich CURRENT OF nicht mit meinen anderen beiden Bedingungen kombinieren ,,,

Hat jemand eine Idee oder eine Alternative?

Gruß thejoker2305

Content-ID: 278071

Url: https://administrator.de/contentid/278071

Ausgedruckt am: 22.11.2024 um 00:11 Uhr

Biber
Lösung Biber 22.07.2015 aktualisiert um 22:17:42 Uhr
Goto Top
Moin thejoke2305,

ich würde da nicht so viel Heckmeck drum machen.
Nach meiner optimistischen (aber ungetesteten) Vermutung würdest du mit folgendem SELECT alle Datensätze angezeigt bekommen, die upgedatet werden könnten:
SELECT mt1.*, 
 DATEADD( DAY, -1 , (SELECT min(datum_von) FROM mitarbeitertabelle mt2 
     WHERE mt1.mitarbeiter=mt2.mitarbeiter 
      AND mt2.datum_von > mt1.datum_von)) as newdate 
 FROM mitarbeitertabelle mt1
WHERE EXISTS (
     SELECT 1 FROM mitarbeitertabelle mt3 
         WHERE mt1.mitarbeiter=mt3.mitarbeiter 
        AND mt3.datum_von > mt1.datum_von);

Wenn du das bestätigen kannst, dann wäre das UPDATE-Statement:
UPDATE mitarbeitertabelle mt1 SET DATUM_VON= 
 DATEADD( DAY, -1 , (SELECT min(datum_von) FROM mitarbeitertabelle mt2 
     WHERE mt1.mitarbeiter=mt2.mitarbeiter 
      AND mt2.datum_von > mt1.datum_von))  

WHERE EXISTS (
     SELECT 1 FROM mitarbeitertabelle mt3 
         WHERE mt1.mitarbeiter=mt3.mitarbeiter 
        AND mt3.datum_von > mt1.datum_von);

Feddich.

Grüße
Biber
TheJoker2305
TheJoker2305 22.07.2015 aktualisiert um 20:29:35 Uhr
Goto Top
Hallo Biber,

ist natürlich einfacher als die Cursor Lösung face-smile

Ich arbeite auf einen MS SQL 2008 R2, da klappt der Befehl

UPDATE mitarbeitertabelle mt1
leider nicht.

Wie kann ich das umgehen?


Das SELECT Statement scheint ermal alle Datensätze zu enthalten die geupdatet werden müssen face-smile
Exodus0
Lösung Exodus0 22.07.2015 aktualisiert um 22:17:39 Uhr
Goto Top
Musst nur das "From Tabelle" hinzufügen und auf mt1 kürzen.
Habs noch auf "Datum_bis" abgeändert.

UPDATE mt1 SET DATUM_bis =
	 DATEADD( DAY, -1 , (SELECT min(datum_von) FROM mitarbeitertabelle mt2 
				WHERE mt1.mitarbeiter=mt2.mitarbeiter 
				AND mt2.datum_von > mt1.datum_von))
FROM mitarbeitertabelle mt1
WHERE EXISTS ( SELECT 1 FROM mitarbeitertabelle mt3 
	WHERE mt1.mitarbeiter=mt3.mitarbeiter 
	AND mt3.datum_von > mt1.datum_von);
Biber
Biber 22.07.2015 aktualisiert um 21:49:37 Uhr
Goto Top
Moin Exodus0,

danke für die Korrektur!

Ich versuch mir das ja immer zu merken, dass MSSQL ein "UPDATE x SET <bla>=<whatever> FROM tabelle x" implementiert hat, aber das is' sich so strange....

Und ja, es ist sinnvoller, das DATUM_BIS zu updaten... face-wink

Grüße
Biber
TheJoker2305
TheJoker2305 22.07.2015 um 22:35:55 Uhr
Goto Top
Hallo zusammen,

beide Abfragen haben sehr gut funktioniert, vielen Dank an alle bisher Beteiligten. Das Updaten des Feldes datum_bis anstatt datum_von ahbe ich intuitiv schon umgestellt face-smile.

Ich habe jetzt noch die Herausforderung, dass die Felder "datum_von" und "datum_bis" herkunftsbedingt vom Typ NVARCHAR und im Format YYYYMMDD vorliegen
Aufgrund des verbrauchten Speicherplatzes natürlich suboptimal (Feldlängen 255 ....) Da die Umstellung des Exports aber noch dauern wird, muss eine andere Lösung her.

Nachtrag:
Hier meine Lösung zum Problem, geht bestimmt noch eleganter, aber so funktioniert es zumindest bis der Export angepasst wurde :

UPDATE mt1 SET datum_bis =
	 replace(convert(nvarchar,convert(date,DATEADD( DAY, -1 , (SELECT min(datum_von) FROM Mitarbeitertabelle mt2 
				WHERE mt1.Mitarbeiter=mt2.Mitarbeiter 
				AND mt2.datum_von > mt1.datum_von)),108)),'-','')  
FROM Mitarbeitertabelle mt1
WHERE EXISTS ( SELECT 1 FROM Mitarbeitertabelle mt3 
	WHERE mt1.mitarbeiter=mt3.mitarbeiter 
	AND mt3.datum_von > mt1.datum_von)

An alle Beteiligen ein ganz großes Lob - das Forum ist TOP.

Gruß
TheJoker2305