tutorials.de Buch-Aktion 05/2012
  • [MySQL] Virtuelle Tabelle mit allen Daten im Jahr

    Im Tutorial-Forum kam die Frage auf, wie man eine Virtuelle Tabelle mit Allen Daten eines Jahres erstellen kann.
    Hier mein erweiterter Lösungsvorschlag:

    Lösung
    Ev. gibts noch was schöneres. Aber ich habe hier mal eine virtuelle Tabelle für die Daten von diesem Jahr -10/+17 erstellt und zum Schluss als Beispiel auf das Jahr 2011 eingeschränkt.
    Code SQL:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    
    SELECT *
    FROM
        (
            -- [Datumsliste]
            SELECT
                myYear,
                makedate(years.myYear, daysOfYear.day_in_year) AS mydate
            FROM
                (
                    -- [Tagesnummern]
                    -- Zahlen von 1 bis 400
                    SELECT
                        @day_in_year := @day_in_year +1 AS day_in_year
                    FROM
                        (SELECT @day_in_year :=0) AS vars,
                        -- [VirtualRows1]
                        -- 400 Zeilen
                        (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) AS d1,
                        (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) AS d2,
                        (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS d3,
                        (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS d4
                        -- [/VirtualRows1]
                    -- [/Tagesnummern]
                ) AS daysOfYear,
                (
                    -- [Jahreszahlen]
                    -- Zahlen von 'Aktuelles Jahr'-10 bis 'Aktuelles Jahr' +17
                    SELECT
                        @YEAR := @YEAR+1 AS myYear
                    FROM
                        (SELECT @YEAR := YEAR(NOW()) -10) AS vars,    
                        -- [VirtualRows2]
                        -- 27 Zeilem
                        (SELECT 1 UNION SELECT 2 UNION SELECT 3) AS y1,
                        (SELECT 1 UNION SELECT 2 UNION SELECT 3) AS y2,
                        (SELECT 1 UNION SELECT 2 UNION SELECT 3) AS y3                  
                        -- [/VirtualRows2]
                    -- [/Jahreszahlen]
                ) AS years
            WHERE
                YEAR(makedate(years.myYear, daysOfYear.day_in_year)) = years.myYear
            -- [/Datumsliste]
        ) AS dates
    WHERE
        myYear=2011;

    Ev. lohnt es sich, diese Daten in eine Tabelle zu speichern.

    Erklärung
    Und nu zu der Erklärung.
    Als erstes brauche ich einfach mal mehr als 365 Datensätze. Dies erreiche ich mit der Multiplikation der folgenden UNION-SELECTS
    Code sql:
    1
    2
    3
    4
    5
    6
    7
    
    -- [VirtualRows1]
    -- 400 Zeilen
    (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) AS d1,
    (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) AS d2,
    (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS d3,
    (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS d4
    -- [/VirtualRows1]
    Dieses Resultat wird durchnummeriert mittels der Variable @day_in_year
    Code sql:
    1
    2
    3
    4
    5
    6
    7
    8
    
    -- [Tagesnummern]
    -- Zahlen von 1 bis 400
    SELECT
        @day_in_year := @day_in_year +1 AS day_in_year
    FROM
        (SELECT @day_in_year :=0) AS vars,
        [VirtualRows1]
    -- [/Tagesnummern]

    Als zweite Quelle erstelle ich 27 Zelen für die Jahreszahlen
    Code sql:
    1
    2
    3
    4
    5
    6
    
    -- [VirtualRows2]
    -- 27 Zeilem
    (SELECT 1 UNION SELECT 2 UNION SELECT 3) AS y1,
    (SELECT 1 UNION SELECT 2 UNION SELECT 3) AS y2,
    (SELECT 1 UNION SELECT 2 UNION SELECT 3) AS y3                  
    -- [/VirtualRows2]

    Auch diese kombiniere werden durchnummeriert. Ich fange aber nicht bei 0 an, sondern bei 'aktuelles Jahr minus 10'
    Code sql:
    1
    2
    3
    4
    5
    6
    7
    8
    
    -- [Jahreszahlen]
    -- Zahlen von 'Aktuelles Jahr'-10 bis 'Aktuelles Jahr' +17
    SELECT
        @YEAR := @YEAR+1 AS myYear
    FROM
        (SELECT @YEAR := YEAR(NOW()) -10) AS vars,    
        [VirtualRows2]                  
    -- [/Jahreszahlen]

    Diese Tagesnummern kombiniere ich mit den Jahren und errechnen die Datums.
    Da meine Virtuelle Tabelle 400 Datensätze beinhaltet (5x5x4x4), erhalte ich pro Jahr auch Datums im nächsten Jahr:
    makedate(2010, 400) ergibt ein Datum im Jahre 2011.
    Darum prüfe ich am Schluss nochmals, ob das Jahr übereinstimmt. Da ich die Anzahl Tage nicht auf 365 beschränke, habe ich keine Probleme mit dem Schaltjahr. Das rechnet mir makedate() richtig aus.
    Code sql:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    -- [Datumsliste]
    SELECT
        myYear,
        makedate(years.myYear, daysOfYear.day_in_year) AS mydate
    FROM
        [Tagesnummern]  AS daysOfYear,
        [Jahreszahlen] AS years
    WHERE
        YEAR(makedate(years.myYear, daysOfYear.day_in_year)) = years.myYear
    -- [/Datumsliste]

    Das wars auch schon.
    CookieBuster und ComFreek bedanken sich. 


    Kommentare 5 Kommentare
    1. Avatar von CookieBuster
      CookieBuster -
      Daten!

      Sonst sieht das ganze wirklich gut aus, gefällt mir!
    1. Avatar von ComFreek
      ComFreek -
      Ich finde die Lösung zwar interessant.

      Allerdings frage ich mich gerade wozu man das genau braucht? Sowas geht auch mit PHP ganz einfach.
      Was war denn genau der Hintergrund des Ausgangs-Threads?
    1. Avatar von Yaslaw
      Yaslaw -
      @CokieBuster
      thx

      @ComFreek
      Manchmal sucht man Lösungen ohne Frontend, ohne PHP, einfach nur in SQL....
    1. Avatar von Callboy
      Callboy -
      Sieht soweit Cool aus aber verstehe es trotzdem nicht ...

      Warum - 10 und warum + 17?
      Warum so viele Zeilen und wiederum nicht?
      Warum 5x5x4x4?

      Wenn du deine Gedankensprünge hier auch erwähnst, könnten wir auf dein Tutorials noch durchsteigen ...

      Gruß
      Daniel
    1. Avatar von Yaslaw
      Yaslaw -
      @Callboy

      Warum - 10 und warum + 17?
      Ist einfach eine von mir gesetzte Eingrenzung. Ich habe in [VirtualRows2] 27 Zeilen für die Jahre generiert. Diese müssen noch mit Jahren gefüllt werden. Ich habe da jetzt einfach von heute 10 in die Vergangenheit und 17 in die Zukunft gewählt.
      Man kann auch mehr Virtuelle Zeilen generieren und die Jahre anderst verschieben.

      Warum 5x5x4x4?
      Ich brauche einfach mehr Zeilen als das Jahr Tage hat. Und mit 5x5x4x4 bekomme ich 400 Zeilen. Ich kann auch eine andere Kombination nehmen. Das ist eigentlich egal, solange es mehr als 365 Zeilen erstellt

      Warum so viele Zeilen und wiederum nicht?
      Ich habe mehr Zeilen als Tage pro Jahr. Diese muss iach dann auf die Tage pro Jahr kürzen..
    Kommentare Kommentar schreiben

    Klicke hier, um dich anzumelden

    Wie nennt man ein vierbeiniges Tier, das bellen kann?