Information ausblenden
Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm

Tabellen vereinigen mit UNION

Dieses Thema im Forum "MySQL und MariaDB" wurde erstellt von DiegoP, 7 Dezember 2013.

  1. DiegoP

    DiegoP Neuer Benutzer

    Hallo,

    ich stehe hier gerade vor einem Problem, wonach ich gegoogelt habe, eine Lösung gefunden und auf mein Problem angewendet habe, leider ist das Ergebnis nicht das erwartete.

    Ich habe hier verschiedene Views aus Tabellen erstellt.
    In einem View "Jahre" stehen nur Jahre von 2007 - 2013 drin, also:
    Code:
    |Jahr|
    |2007|
    |2008|
    |2009|
    |2010|
    |2011|
    |2012|
    |2013|
    
    Dann habe ich 3 weitere Tabellen, welche jeweils als Spalte ein Jahr beinhalten sowie einen bestimmten Wert.
    Diese Tabellen müssen aber nicht alle Jahre beinhalten, z.B:
    Code:
    "tab1"
    |Jahr|Wert_1|
    |2007|   100|
    |2009|   120|
    |2011|   130|
    
    und

    Code:
    "tab2"
    |Jahr|Wert_2|
    |2007|   110|
    |2008|    20|
    |2009|   130|
    |2011|   140|
    |2012|   120|
    
    und

    Code:
    "tab3"
    |Jahr|Wert_3|
    |2008|   200|
    |2009|   220|
    |2010|   150|
    |2013|   200|
    
    Ich möchte nun alle 4 Tabellen miteinander verbinden, d.h. am Ende eine Tabelle haben mit diesem Format:
    Code:
    |Jahr|Wert_1|Wert_2|Wert_3|
    |2007|   100|   110|    - |
    |2008|    - |    20|   200|
    |2009|   120|   130|   220|
    |2010|    - |    - |   150|
    |2011|   130|   140|    - |
    |2012|    - |   120|    - |
    |2013|    - |    - |   200|
    
    Dafür habe ich mir ein Query überlegt, welches folgendermaßen aussieht:
    Code:
    SELECT
    j.Jahr AS 'Jahr',
    t1.Wert_1 AS 'Wert_1',
    '' AS 'Wert_2',
    '' AS 'Wert_3'
    FROM Jahre j
    LEFT JOIN
    tab1 t1
    ON j.Jahr = t1.Jahr
    
    UNION
    
    SELECT
    j.Jahr AS 'Jahr',
    '' AS 'Wert_1',
    t2.Wert_2 AS 'Wert_2',
    '' AS 'Wert_3'
    FROM Jahre j
    LEFT JOIN
    tab2 t2
    ON j.Jahr = t2.Jahr 
    
    UNION
    
    SELECT
    j.Jahr AS 'Jahr',
    '' AS 'Wert_1',
    '' AS 'Wert_2',
    t3.Wert_3 AS 'Wert_3'
    FROM Jahre j
    LEFT JOIN
    tab2 t3
    ON j.Jahr = t3.Jahr
    
    Ich habe es auch schon mit UNION ALL versucht, aber die Spalten werden nicht "nebeneinander" gestellt, sondern immer sowas:

    Code:
    |Jahr|Wert_1|Wert_2|Wert_3|
    |2007|   100|      |      |
    |2008|      |      |      |
    |2009|   120|      |      |
    |2010|      |      |      |
    |2011|   130|      |      |
    |2012|      |      |      |
    |2013|      |      |      |
    |2007|      |   110|      |
    |2008|      |    20|      |
    |2009|      |   130|      |
    |2010|      |      |      |
    |2011|      |   140|      |
    |2012|      |   120|      |
    |2013|      |      |      |
    |2007|      |      |      |
    |2008|      |      |   200|
    |2009|      |      |   220|
    |2010|      |      |   150|
    |2011|      |      |      |
    |2012|      |      |      |
    |2013|      |      |   200|
    
    Weiss jemand, woran das liegen könnte?
     
  2. akretschmer

    akretschmer Datenbank-Guru

    Du bist nah dran. Über das Resultat, was Du bekommst, aggregierst Du. Du summierst die Werte und gruppierst nach Jahr. Das schaffst Du.
    Einzig, was noch knifflig werden könnte, ist, daß Deine Werte offenbar vom falschen Datentyp sind. Du wirst Dich, falls dem so ist, mit dem CASTen befreunden müssen.
     
  3. akretschmer

    akretschmer Datenbank-Guru

    Btw.: UNION ALL macht was anderes: während UNION doppelte Zeilen ausfiltert macht UNION ALL dies nicht. UNION ALL ist zwar schneller, macht aber eben nicht das, was Du suchst ;-)
     
  4. DiegoP

    DiegoP Neuer Benutzer

    Ah danke sehr!
    Es funktioniert mit GROUP BY und SUM.
    Zwar umständlich, aber es klappt :)

    Jetzt noch eine weitere Frage:
    Ich habe nun viele Tabellen mit der gleichen Struktur, kann ich die Einträge aller Tabellen irgendwie als eine "lange" zusammenführen?
     
  5. Hubertus

    Hubertus Fleissiger Benutzer

    So geht's auch:

    Code:
    SELECT
    j.Jahr AS 'Jahr',
    t1.Wert_1 AS 'Wert_1',
    t2.Wert_2 AS 'Wert_2',
    t3.Wert_3 AS 'Wert_3'
    FROM Jahre j
    LEFT JOIN
    tab1 t1
    ON j.Jahr = t1.Jahr
    LEFT JOIN
    tab2 t2
    ON j.Jahr = t2.Jahr
    LEFT JOIN
    tab3 t3
    ON j.Jahr = t3.Jahr
    ORDER BY Jahr
    Die Frage
    verstehe ich nicht.
     
  6. akretschmer

    akretschmer Datenbank-Guru

    Warum? Das klingt nach einem falschen Design, sonst würdest Du nicht so fragen.

    Wenn man es richtig macht, kann man beliebig viele Tabellen gleicher Struktur haben und nur eine abfragen und dennoch das Resultat aus allen bekommen: nennt sich Table Partitioning. Lohnt sich erst ab 1-10 Millionen Zeilen pro Kindtabelle und geht so:

    Code:
    test=# create table master_table (id serial primary key, val int);  
    CREATE TABLE  
    Time: 6,187 ms  
    test=*# create table p0 (check(val % 3 = 0)) inherits (master_table);
    CREATE TABLE  
    Time: 1,158 ms  
    test=*# create table p1 (check(val % 3 = 1)) inherits (master_table);
    CREATE TABLE  
    Time: 1,269 ms  
    test=*# create table p2 (check(val % 3 = 2)) inherits (master_table);
    CREATE TABLE
    Time: 1,118 ms
    
    An der Stelle müßte nun noch ein Trigger erstellt werden, der bei Inserts in die master_tabelle den Insert in die richtige p[012] - Tabelle leiten, ich mache es mal händisch:

    Code:
    test=*# insert into p0 (val) values (3);
    INSERT 0 1
    Time: 0,418 ms
    test=*# insert into p0 (val) values (6);
    INSERT 0 1
    Time: 0,196 ms
    test=*# insert into p1 (val) values (7);
    INSERT 0 1
    Time: 0,381 ms
    test=*#
    test=*#
    test=*# select * from master_table where val % 3 = 0;
    id | val
    ----+-----
      1 |  3
      2 |  6
    (2 rows)
    
    Wie man sieht, inserte ich in die pX - Tabellen, frage aber nur die master_table ab. Aufgrund der Constraints werden auch nur die (immer) die master_tabelle und die korrekte pX - Tabelle abgefragt:

    Code:
    test=*# explain select * from master_table where val % 3 = 0;
      QUERY PLAN
    ------------------------------------------------------------------
    Append  (cost=0.00..42.10 rows=12 width=8)
      ->  Seq Scan on master_table  (cost=0.00..0.00 rows=1 width=8)
      Filter: ((val % 3) = 0)
      ->  Seq Scan on p0  (cost=0.00..42.10 rows=11 width=8)
      Filter: ((val % 3) = 0)
    (5 rows)
    
    Ein Insert in die falsche pX - Tabelle schlägt natürlich fehl:

    Code:
    test=*# insert into p2 (val) values (7);
    ERROR:  new row for relation "p2" violates check constraint "p2_val_check"
    DETAIL:  Failing row contains (4, 7).
    Time: 0,303 ms
    
    Du brauchst das in Deinem MySQL jetzt aber nicht nachmachen, das kann das nicht oder nur halb oder so.

    Erkläre aber, warum Du so eine Struktur hast, ohne zu wissen, wie man es 'richtig' macht.
     
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden