MySQL Schleife in Stored Procedure
Hallo,
ich bin gerade echt am grübeln. Ich habe in meiner DB, bestimmte Zeiträume gespeichert.
z.B.
User_ID ; von Datum ; bisDatum ; AnzTage
1; 2019-10-14;2019-10-27;14
2; 2019-06-03;2019-06-14;12
Ich brächte eine Stored Procedure ,die über die Tage zählt und mir eine Liste der Tage ausgibt:
User_id; Tage; Wert(fest)
1;2019-10-14; X
1;2019-10-15; X
.
.
.
1;2019-10.27;X
...
2;2019-06-03;X
2;2019-06-04;X
.
.
.
2;2019-06-14;X
usw.
Ich hoffe mein Anliegen ist klar, kann mir jemand sagen wie ich das in MySQL umsetzen kann?
Vielen Dank!
Gruß Alex
ich bin gerade echt am grübeln. Ich habe in meiner DB, bestimmte Zeiträume gespeichert.
z.B.
User_ID ; von Datum ; bisDatum ; AnzTage
1; 2019-10-14;2019-10-27;14
2; 2019-06-03;2019-06-14;12
Ich brächte eine Stored Procedure ,die über die Tage zählt und mir eine Liste der Tage ausgibt:
User_id; Tage; Wert(fest)
1;2019-10-14; X
1;2019-10-15; X
.
.
.
1;2019-10.27;X
...
2;2019-06-03;X
2;2019-06-04;X
.
.
.
2;2019-06-14;X
usw.
Ich hoffe mein Anliegen ist klar, kann mir jemand sagen wie ich das in MySQL umsetzen kann?
Vielen Dank!
Gruß Alex
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 431098
Url: https://administrator.de/contentid/431098
Ausgedruckt am: 14.11.2024 um 13:11 Uhr
16 Kommentare
Neuester Kommentar
Das geht , abhängig von der MySQL Version, auch ohne SP und Schleife, Schleifen sind das letzte Mittel. Notwendig dafür ist CTE:
https://dev.mysql.com/doc/refman/8.0/en/with.html
Kannst du keine aktuelle Version nutzen wäre eine Schleife denkbar. Es müsste aber eine temporäre Tabelle oder eine Tabellenvariable genutzt werden.
https://dev.mysql.com/doc/refman/8.0/en/with.html
Kannst du keine aktuelle Version nutzen wäre eine Schleife denkbar. Es müsste aber eine temporäre Tabelle oder eine Tabellenvariable genutzt werden.
so vielleicht?
[code]
test=*# select * from facebraker ;
id | von | bis
+------------+------------
1 | 2019-10-14 | 2019-10-27
2 | 2019-06-03 | 2019-06-14
(2 rows)
test=*# select f.von, f.bis, x.wert::date from facebraker f left join lateral (select * from generate_series(f.von, f.bis, '1day'::interval) as wert) x on (true);
von | bis | wert
+------------+------------
2019-10-14 | 2019-10-27 | 2019-10-14
2019-10-14 | 2019-10-27 | 2019-10-15
2019-10-14 | 2019-10-27 | 2019-10-16
2019-10-14 | 2019-10-27 | 2019-10-17
2019-10-14 | 2019-10-27 | 2019-10-18
2019-10-14 | 2019-10-27 | 2019-10-19
2019-10-14 | 2019-10-27 | 2019-10-20
2019-10-14 | 2019-10-27 | 2019-10-21
2019-10-14 | 2019-10-27 | 2019-10-22
2019-10-14 | 2019-10-27 | 2019-10-23
2019-10-14 | 2019-10-27 | 2019-10-24
2019-10-14 | 2019-10-27 | 2019-10-25
2019-10-14 | 2019-10-27 | 2019-10-26
2019-10-14 | 2019-10-27 | 2019-10-27
2019-06-03 | 2019-06-14 | 2019-06-03
2019-06-03 | 2019-06-14 | 2019-06-04
2019-06-03 | 2019-06-14 | 2019-06-05
2019-06-03 | 2019-06-14 | 2019-06-06
2019-06-03 | 2019-06-14 | 2019-06-07
2019-06-03 | 2019-06-14 | 2019-06-08
2019-06-03 | 2019-06-14 | 2019-06-09
2019-06-03 | 2019-06-14 | 2019-06-10
2019-06-03 | 2019-06-14 | 2019-06-11
2019-06-03 | 2019-06-14 | 2019-06-12
2019-06-03 | 2019-06-14 | 2019-06-13
2019-06-03 | 2019-06-14 | 2019-06-14
(26 rows)
test=*#
[/code]
allerdings müßtest Du Dein MySQL gegen PostgreSQL austauschen.
[code]
test=*# select * from facebraker ;
id | von | bis
+------------+------------
1 | 2019-10-14 | 2019-10-27
2 | 2019-06-03 | 2019-06-14
(2 rows)
test=*# select f.von, f.bis, x.wert::date from facebraker f left join lateral (select * from generate_series(f.von, f.bis, '1day'::interval) as wert) x on (true);
von | bis | wert
+------------+------------
2019-10-14 | 2019-10-27 | 2019-10-14
2019-10-14 | 2019-10-27 | 2019-10-15
2019-10-14 | 2019-10-27 | 2019-10-16
2019-10-14 | 2019-10-27 | 2019-10-17
2019-10-14 | 2019-10-27 | 2019-10-18
2019-10-14 | 2019-10-27 | 2019-10-19
2019-10-14 | 2019-10-27 | 2019-10-20
2019-10-14 | 2019-10-27 | 2019-10-21
2019-10-14 | 2019-10-27 | 2019-10-22
2019-10-14 | 2019-10-27 | 2019-10-23
2019-10-14 | 2019-10-27 | 2019-10-24
2019-10-14 | 2019-10-27 | 2019-10-25
2019-10-14 | 2019-10-27 | 2019-10-26
2019-10-14 | 2019-10-27 | 2019-10-27
2019-06-03 | 2019-06-14 | 2019-06-03
2019-06-03 | 2019-06-14 | 2019-06-04
2019-06-03 | 2019-06-14 | 2019-06-05
2019-06-03 | 2019-06-14 | 2019-06-06
2019-06-03 | 2019-06-14 | 2019-06-07
2019-06-03 | 2019-06-14 | 2019-06-08
2019-06-03 | 2019-06-14 | 2019-06-09
2019-06-03 | 2019-06-14 | 2019-06-10
2019-06-03 | 2019-06-14 | 2019-06-11
2019-06-03 | 2019-06-14 | 2019-06-12
2019-06-03 | 2019-06-14 | 2019-06-13
2019-06-03 | 2019-06-14 | 2019-06-14
(26 rows)
test=*#
[/code]
allerdings müßtest Du Dein MySQL gegen PostgreSQL austauschen.
<Edit>
vergiss nachfolgendes. Nach nochmaligem lesen willst du ja den umgekehrten Weg -.-
<\edit>
Also wenn ich dich richtig verstanden habe, willst du für einen User das erste und das letzte Datum wissen und dann beide Daten von einander abziehen in die Zahl der Tage zu erhalten?
Warum dann nicht die Tabelle nochmal mit sich selbst joinen, die UserId als Key:
Oben die Differenz beider Tage musst du noch mit der richtigen Syntax versehen, da fehlt sicherlich noch ein Convert as date und ein FORMAT, dass dort Tage und kein Datum bei rauskommt...
Gruß
em-pie
vergiss nachfolgendes. Nach nochmaligem lesen willst du ja den umgekehrten Weg -.-
<\edit>
Also wenn ich dich richtig verstanden habe, willst du für einen User das erste und das letzte Datum wissen und dann beide Daten von einander abziehen in die Zahl der Tage zu erhalten?
Warum dann nicht die Tabelle nochmal mit sich selbst joinen, die UserId als Key:
Select a.User, a.MinDate, b.MaxDate, b.MaxDate - a.MinDate as Tage
From
(select Userid, Min(Datum) as MinDate GROUP by Userid) as a
Left Join
(Select Userid, Max(Datum) as MaxDate GROUP by Userid ) as b on a.Userid = b.Userid
Oben die Differenz beider Tage musst du noch mit der richtigen Syntax versehen, da fehlt sicherlich noch ein Convert as date und ein FORMAT, dass dort Tage und kein Datum bei rauskommt...
Gruß
em-pie
MSSQL (MySQL vielleicht mit der richtigen Version)
in performant:
In langsam und fehleranfällig möchte ich das eigentlich gar nicht schreiben. Es geht aber auch per Cursor oder WHILE-Schleife innerhalb einer Funktion. Die muss dann irgendwo in eine Tabelle schreiben oder eine Tabellenvariable ausspucken.
in performant:
WITH tabelle(id,von,bis) AS (
SELECT 1,convert(DATE,'2019-10-14',20),convert(DATE,'2019-10-27',20) UNION ALL
SELECT 2,'2019-06-03','2019-06-14'
), t(id,von,bis,datum) AS (
SELECT tabelle.id,tabelle.von,tabelle.bis,tabelle.von
FROM tabelle
UNION ALL
SELECT t.id,t.von,t.bis,dateadd(day,1,t.datum)
FROM t
WHERE dateadd(day,1,t.datum) <= t.bis
)
SELECT t.id,
t.datum
FROM t
ORDER BY t.id,t.datum
In langsam und fehleranfällig möchte ich das eigentlich gar nicht schreiben. Es geht aber auch per Cursor oder WHILE-Schleife innerhalb einer Funktion. Die muss dann irgendwo in eine Tabelle schreiben oder eine Tabellenvariable ausspucken.
Hier mal mit Funktion, Temp-Tabelle und Tabellen-Variable in der Funktion. Ist auch ein MSSQL Beispiel aber möglicherweise auf MySQL übertragbar.
CREATE TABLE #tabelle(id SMALLINT,von DATE,bis DATE)
INSERT INTO #tabelle
SELECT 1,convert(DATE,'2019-10-14',20),convert(DATE,'2019-10-27',20)
INSERT INTO #tabelle
SELECT 2,convert(DATE,'2019-06-03',20),convert(DATE,'2019-06-14',20)
CREATE FUNCTION [dbo].[wusa](@von DATE,@bis DATE)
RETURNS @dates TABLE(datum DATE)
AS
BEGIN
WHILE @von <= @bis
BEGIN
INSERT INTO @dates(datum)
VALUES(@von)
SET @von = dateadd(day,1,@von)
END
RETURN
END
SELECT #tabelle.id,
f.*
FROM #tabelle
CROSS APPLY [dbo].[wusa](von,bis) f