======[MySQL] Virtuelle Tabelle mit allen Daten eines Monats====== =====Aufgabenstellung===== Ich will für jeden Tag im Monat eine Zeile haben in der das Datum steht. Es liegt keine Tabelle zugrunde. ^ mydate ^ | 2012-11-01 | | 2012-11-02 | | ... | | 2012-11-29 | | 2012-11-30 | =====Lösungen===== Ähnlich, jedoch einfacher wie [[:MySql:CreateAllDatesOfYear]] ist es, alle Daten eines Monats zu ermitteln Und natürlich führen viele Wege nach Rom. Ich habe hier mal 2 Beispiele wie man sowas bewerkstelligen könnte. In beiden ermittle ich alle Tage im November 2012. Das Reusltat ist bei beiden dasselbe ====Lösung 1: Tagesnummer hochzählen, ein Datumsstring zusammensetzen und parsen==== Mit einem Zähler (@day_in_month) für jeden Tag das Datum erstellen ===SQL Statement=== SELECT days_in_month.mydate FROM ( SELECT vars.selected_month, -- Tag hochzählen @day_in_month := @day_in_month + 1 AS day_in_month, -- Ein Datumsstring zusammensetzen und als Datum parsen STR_TO_DATE(CONCAT_WS('-',@day_in_month, vars.selected_month, vars.selected_year), '%d-%m-%Y') AS mydate FROM -- 6^2 Zeilen erstellen: Also 36. (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6) AS d1, (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6) AS d2, -- Variablen instanzieren. Hier der November 2012 (SELECT @day_in_month :=0, 2012 AS selected_year, 11 AS selected_month) AS vars ) AS days_in_month WHERE -- Nur die gültigen Tage auswählen. Zur erinnerung, wir haben 36 Zeilen.... MONTH(days_in_month.mydate) = days_in_month.selected_month; ===Erklärbär=== ==[Grid] Zeilen zur Verfügung stellen== Ich erstelle 36 virtuelle Zeilen. Dazu nehme ich 2 UNION-Queries mit je 6 Einträgen die ich unverknüpft zusammenführe. -- [GRID] -- 6^2 Zeilen erstellen: Also 36. (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6) AS d1, (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6) AS d2, ==[Vars] Variablen initialisieren== Dann erstelle ich ein weiteres Subquery um die Variablen zu setzen -- VARS] SELECT @day_in_month :=0, -- -- 2012 AS selected_year, 11 AS selected_month -- -- ==[Calc] Berechnen der Tage== Diese werden nun zusammengeführt. Somit habe ich die Initialisierten Variablen und 36 Zeilen. Damit lässt sich wunderschön arbeiten -- [CALC] SELECT vars.selected_month, -- Tag hochzählen @day_in_month := @day_in_month + 1 AS day_in_month, -- Ein Datumsstring zusammensetzen und als Datum parsen STR_TO_DATE(CONCAT_WS('-',@day_in_month, vars.selected_month, vars.selected_year), '%d-%m-%Y') AS mydate FROM [GRID], [VARS] Zuerst erhöhe ich immer @day_in_month um 1. Anschliessend setze ich mit dem Jahr, Monat und dem @day_in_month einen Datumsstring zusammen: ##[DATE_STRING] = CONCAT_WS('-',@day_in_month, vars.selected_month, vars.selected_year)## DIeser wird nun noch in ein gültiges Datum gewandelt ##STR_TO_DATE([DATE_STRING], '%d-%m-%Y')## ==ungültige Ausfiltern== Am Schluss haben wir natürlich das Problem, dass wir 36 Zeilen haben. Wir brauchen aber nu 28 bis 31, je nach Monat. STR_TO_DATE() kann mit einem Datumsstring '35-11-2012' nix anfangen und gibt da darum NULL zurück. Um nun sicher zu sein, dass ich nur Tage meines ausgewählten Monat habe, setzen ich das ganze nochmals in ein Query und vergleiche den Monat des ermittelten Tages mit dem selektierten Monat. SELECT days_in_month.mydate FROM [CALC] AS days_in_month WHERE -- Nur die gültigen Tage auswählen. Zur erinnerung, wir haben 36 Zeilen.... MONTH(days_in_month.mydate) = days_in_month.selected_month; ====Lösung 2: Das Datum hochrechnen==== Und zum zeigen das viele Wege nach Rom führen. Das Datum des letzten tages vor dem Monat ermitteln und dann für jeden Tag ein Tag dazurechnen. ===SQL-Statement=== SELECT days_in_month.mydate FROM ( SELECT vars.selected_month, -- Tag im Monat hochzählen @act_date := DATE_ADD(@act_date, INTERVAL 1 DAY) AS mydate FROM -- 6^2 Zeilen erstellen: Also 36. (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6) AS d1, (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6) AS d2, -- Variablen instanzieren ( SELECT @selected_year := 2012, @selected_month := 11 AS selected_month, -- Letzter Tag im Vormonat ermitteln @act_date := DATE_SUB(STR_TO_DATE(CONCAT_WS('-',1, @selected_month, @selected_year), '%d-%m-%Y'), INTERVAL 1 DAY) ) AS vars ) AS days_in_month WHERE -- Nur die gültigen Tage auswählen. Zur erinnerung, wir haben 36 Zeilen.... MONTH(days_in_month.mydate) = days_in_month.selected_month; ===Erklärbär=== ==[Grid] Zeilen zur Verfügung stellen== Das [GRID] ist dasselbe wie bereits im ersten Beispiel ==[Vars] Variablen initialisieren== Hier ist ein wenig mehr. Ich erstelle aus den Parameter gleich das Datum des letzten Tages des Vormonates. Dazu setze ich wieder ein Datum-String auf den ersten des Monats und zieh 1 Tag ab. Somit erhalte ich den letzten Tag des Vormonats in der Variable @act_date. -- [VARS] SELECT -- -- @selected_year := 2012, @selected_month := 11 AS selected_month, -- -- @day_in_month :=0, -- Letzter Tag im Vormonat ermitteln @act_date := DATE_SUB(STR_TO_DATE(CONCAT_WS('-',1, @selected_month, @selected_year), '%d-%m-%Y'), INTERVAL 1 DAY) ==[Calc] Berechnen der Tage== Dafür ist die Berechnung nachher umso einfacher. Einfach jedesmal 1 Tag zu @act_date dazurechnen. -- [CALC] SELECT vars.selected_month, -- Tag im Monat hochzählen @act_date := DATE_ADD(@act_date, INTERVAL 1 DAY) AS mydate FROM [GRID], [VARS] ==ungültige Ausfiltern== Das funktioniert genauso wie beim ersten Beispiel. {{tag>MySQL Date}}