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

Daten aus zwei Tabellen zusammenführen

Dieses Thema im Forum "MySQL und MariaDB" wurde erstellt von voumi, 25 Juli 2020.

  1. voumi

    voumi Benutzer

    Hallo zusammen

    Vielleicht wurde dieses Thema hier bereits behandelt. Momentan stehe ich aber so etwas von auf dem Schlauch, dass ich noch nicht einmal herausgefunden habe, nach welchen Stichworten ich suchen kann....

    Ich habe (nebst anderen) zwei "Tabellen". In der ersten (adm_user_data) gibt es (unter anderen) eine Spalte "usd_usr_id", eine mit "usd_usf_id" und eine "usd_value". In der ersten steht eine personenbezogene Zahl. In der zweiten eine Zahl, welche dem Feldtyp entspricht - zum Beispiel 1 für Nachname und 2 für Vornamen. In der zweiten Tabelle (adm_members) heissten die relevanten Spalten "mem_rol_id", "mem_usr_id" und "mem_begin". Die Daten aus "mem_begin" möchte ich nun pro Spalte nach "mem_rol_id" sortieren. Vielleicht hilft an dieser Stelle ein Bild (was ich habe und was ich möchte) zum besseren Verständnis:

    upload_2020-7-25_21-35-35.png

    Mittels folgendem Code kann ich die Daten einer Rolle (Im Beispiel 39) anzeigen lassen.

    Kann mir jemand einen Tipp geben, wie ich die weiteren Spalten angefügt bekomme?

    Besten Dank bereits im Voraus.

    Liebe Grüsse
    voumi

    <code>
    SELECT usr_id,


    CONCAT(id1.usd_value) AS nachname, CONCAT(id2.usd_value) AS vorname, YEAR(CONCAT(id10.usd_value)) AS Jahrgang, rol_id, rol_sequence, rol_name, YEAR(mem_begin), YEAR(mem_end)

    FROM adm_roles, adm_categories, adm_members, adm_users

    LEFT JOIN adm_user_data id1 ON id1.usd_usr_id = usr_id

    AND id1.usd_usf_id = 1

    LEFT JOIN adm_user_data id2 ON id2.usd_usr_id = usr_id

    AND id2.usd_usf_id = 2

    LEFT JOIN adm_user_data id10 ON id10.usd_usr_id = usr_id

    AND id10.usd_usf_id = 10

    WHERE rol_id = 39 AND mem_begin <= NOW() AND mem_end > NOW()

    AND rol_valid = 1

    AND rol_cat_id = cat_id

    AND cat_org_id = 1

    AND mem_rol_id = rol_id

    AND mem_usr_id = usr_id

    AND usr_valid = 1

    ORDER BY nachname ASC, vorname ASC
    </code>
     
  2. dabadepdu

    dabadepdu Datenbank-Guru

    Ziemlich durcheinander Dein Statement. Könnte man mal umbauen auf eine einheitliche Art joins, am besten Ansi Join Syntax. Dann könnte man es ordentlich formatieren.
    Dann würde man es vielleicht lesen und verstehen können.

    Du musst dem Vorgehen bei den Spalten mit dem Namen "usd_usf_id" folgen und darüber einen gewünschten Ausgabewert filtern. Dazu brauchst Du jeweils einen neuen Join mit einem neuen Alias (siehe Aliase id1, id2, id10 als Vorlage).

    Warum ist das Concat da drin?
     
  3. voumi

    voumi Benutzer

    Vielen Dank, dabadepdu, für Deine schnelle Antwort und die Stichworte, nach denen ich nun suchen und mich einlesen kann. Das Statement habe ich "gestohlen"/zusammen geklickt und muss leider gestehen, dass ich es auch nicht wirklich verstehe - jedenfalls nicht in allen Teilen. Deshalb kann ich Deine Frage nach dem Concat auch (noch) nicht wirklich beantworten. (Schliesse aber aus Deiner Antwort, dass es nicht wirklich nötig ist.)
     
  4. akretschmer

    akretschmer Datenbank-Guru

    mir scheint, Du willst sowas:

    Code:
    test=*# select * from adm_user_data ;
     usd_usr_id | usd_usf_id | usd_value
    ------------+------------+-----------
              1 |          1 | nachname1
              1 |          2 | vorname1
              1 |          3 | geb1
              2 |          1 | nachname2
              2 |          2 | vorname2
              2 |          3 | geb2
              3 |          1 | nachmane3
              3 |          3 | geb3
              4 |          1 | nachname4
              4 |          2 | vorname4
              4 |          3 | geb4
              3 |          2 | vorname3
    (12 rows)
    
    test=*# select * from adm_members ;
     mem_rol_id | mem_usr_id | mem_begin 
    ------------+------------+------------
             39 |          1 | 1990-01-01
             36 |          1 | 1993-03-03
             37 |          1 | 1996-05-01
             38 |          1 | 1999-07-01
             39 |          2 | 2002-08-30
             36 |          2 | 2005-10-29
             39 |          3 | 2008-12-28
             39 |          4 | 2012-02-27
             36 |          4 | 2015-04-28
             37 |          4 | 2018-06-12
             38 |          4 | 2019-08-26
             69 |          4 | 2014-10-25
    (12 rows)
    
    test=*# select usd_usr_id,string_agg(case when usd_usf_id = 1 then usd_value else null end,'') as nachname, string_agg(case when usd_usf_id = 2 then usd_value else null end,'') as vorname, string_agg(case when usd_usf_id = 3 then usd_value else null end,'') as geb_dat, a36.mem_begin as "36", a37.mem_begin as "37", a38.mem_begin as "38" from adm_user_data left join adm_members a36 on (a36.mem_usr_id=adm_user_data.usd_usr_id and a36.mem_rol_id=36) left join adm_members a37 on (a37.mem_usr_id=adm_user_data.usd_usr_id and a37.mem_rol_id=37) left join adm_members a38 on (a38.mem_usr_id=adm_user_data.usd_usr_id and a38.mem_rol_id=38) group by usd_usr_id, a36.mem_begin, a37.mem_begin, a38.mem_begin order by usd_usr_id;
     usd_usr_id | nachname  | vorname  | geb_dat |     36     |     37     |     38    
    ------------+-----------+----------+---------+------------+------------+------------
              1 | nachname1 | vorname1 | geb1    | 1993-03-03 | 1996-05-01 | 1999-07-01
              2 | nachname2 | vorname2 | geb2    | 2005-10-29 |            |
              3 | nachmane3 | vorname3 | geb3    |            |            |
              4 | nachname4 | vorname4 | geb4    | 2015-04-28 | 2018-06-12 | 2019-08-26
    (4 rows)
    
    Für die 69-iger Spalte war ich jetzt einfach zu faul, ich denke aber, Du siehst den Weg.

    Bitte in Zukunft keine Bilder, die bekommt man so schlecht via Copy&Paste als Daten in eine Tabelle. Ach ja: wie bei mir üblich wurde PostgreSQL verwendet. Die Realisierung in anderen Systemen kann davon abweichen.
     
    Zuletzt bearbeitet: 26 Juli 2020
  5. akretschmer

    akretschmer Datenbank-Guru

    hab es mal noch etwas lesefreundlicher formatiert:

    Code:
    test=*# select
      usd_usr_id
      , string_agg(case when usd_usf_id = 1 then usd_value else null end,'') as nachname
      , string_agg(case when usd_usf_id = 2 then usd_value else null end,'') as vorname
      , string_agg(case when usd_usf_id = 3 then usd_value else null end,'') as geb_dat
      , a36.mem_begin as "36"
      , a37.mem_begin as "37"
      , a38.mem_begin as "38"
    from
      adm_user_data
      left join adm_members a36 on (a36.mem_usr_id=adm_user_data.usd_usr_id and a36.mem_rol_id=36)
      left join adm_members a37 on (a37.mem_usr_id=adm_user_data.usd_usr_id and a37.mem_rol_id=37)
      left join adm_members a38 on (a38.mem_usr_id=adm_user_data.usd_usr_id and a38.mem_rol_id=38)
    group by
      usd_usr_id
      , a36.mem_begin
      , a37.mem_begin
      , a38.mem_begin
    order by
      usd_usr_id;
     usd_usr_id | nachname  | vorname  | geb_dat |     36     |     37     |     38     
    ------------+-----------+----------+---------+------------+------------+------------
              1 | nachname1 | vorname1 | geb1    | 1993-03-03 | 1996-05-01 | 1999-07-01
              2 | nachname2 | vorname2 | geb2    | 2005-10-29 |            |
              3 | nachmane3 | vorname3 | geb3    |            |            |
              4 | nachname4 | vorname4 | geb4    | 2015-04-28 | 2018-06-12 | 2019-08-26
    (4 rows)
    
    test=*#
    
     
    Walter gefällt das.
  6. voumi

    voumi Benutzer

    Vielen Dank für die Tipps. Das Bild war dazu gedacht, etwas Licht in meine, für mich ungewöhnlich gegliederte, Tabellen zu bringen. Daran, dass jemand damit ein Beispiel für mich zaubert, hätte ich im Traum nicht gedacht....
    Mein Problem - ok.... eines meiner Probleme - ist, dass ich keine "Spalten" mit Namen, Vornamen etc. habe. Auch mit PostgreSQL bin ich bisher noch nicht in Berührung gekommen. Momentan bin ich aber noch zuversichtlich, dass ich es hinbekommen werde.
    Nochmals ganz herzlichen Dank für die Inputs.
     
  7. akretschmer

    akretschmer Datenbank-Guru

    Das nennt sich EAV-Modell (Entity Attribute Value). Das wird recht oft in Datenbanken eingesetzt, die keine besseren Datentypen kennen. Also z.B. MySQL. In PostgreSQL steht für sowas schon seit Ewigkeiten HSTORE als Key-Value-Datentyp und seit einigen Jahren auch JSON bzw. JSONB zur Verfügung. Siehe z.B. Entity-Attribute-Value Model (EAV)
     
  8. voumi

    voumi Benutzer

    Super! Besten Dank. Damit versuche ich, meine Wissenslücken zu verkleinern. :):):)
     
    akretschmer gefällt das.
  9. voumi

    voumi Benutzer

    Es hat geklappt - auch wenn ich das mit dem ANSI Join Syntax nicht wirklich herausgefunden habe....
    Besten Dank Euch beiden.
    Der Vollständigkeit halber hier mein funktionierender Code:


    Code:
    SELECT usr_id,
    
    id1.usd_value AS nachname, id2.usd_value AS vorname, YEAR (id10.usd_value) AS jahrgang, rol_name, YEAR(r36.mem_begin) AS 'kvet', YEAR(r37.mem_begin) AS 'evet', YEAR(r38.mem_begin) AS 'kevet', YEAR(r69.mem_begin) AS cism, YEAR(r77.mem_begin) AS 'eevet', YEAR(akt.mem_end) AS 'aktbis'
    
    FROM adm_roles, adm_categories, adm_members, adm_users
    
    LEFT JOIN adm_user_data id1 ON id1.usd_usr_id = usr_id
    AND id1.usd_usf_id = 1
    
    LEFT JOIN adm_members r39 ON r39.mem_usr_id = usr_id
    AND r39.mem_rol_id = 39
    
    LEFT JOIN adm_members r36 ON r36.mem_usr_id = usr_id
    AND r36.mem_rol_id = 36
    
    LEFT JOIN adm_members r37 ON r37.mem_usr_id = usr_id
    AND r37.mem_rol_id = 37
    
    LEFT JOIN adm_members r38 ON r38.mem_usr_id = usr_id
    AND r38.mem_rol_id = 38
    
    LEFT JOIN adm_members r69 ON r69.mem_usr_id = usr_id
    AND r69.mem_rol_id = 69
    
    LEFT JOIN adm_members r77 ON r77.mem_usr_id = usr_id
    AND r77.mem_rol_id = 77
    
    LEFT JOIN adm_members akt ON akt.mem_usr_id = usr_id
    AND akt.mem_rol_id = 2
    
    LEFT JOIN adm_user_data id2 ON id2.usd_usr_id = usr_id
    AND id2.usd_usf_id = 2
    
    LEFT JOIN adm_user_data id10 ON id10.usd_usr_id = usr_id
    AND id10.usd_usf_id = 10
    
    WHERE rol_id = 39 AND r39.mem_begin <= NOW() AND r39.mem_end > NOW() AND akt.mem_end = ('9999-12-31')
    
    AND rol_valid = 1
    AND rol_cat_id = cat_id
    AND cat_org_id = 1
    AND adm_members.mem_rol_id = rol_id
    
    AND adm_members.mem_usr_id = usr_id
    AND usr_valid = 1
    ORDER BY nachname ASC, vorname ASC
     
  10. akretschmer

    akretschmer Datenbank-Guru

    Damit ist gemeint, daß man z.B. schreibt: ...FROM a LEFT JOIN b ON a.id=b.id WHERE ..., und nicht FROM a,b WHERE a.id=b.id AND.
    In der zweiten Form wird die JOIN-Condition mit der/den WHERE-conditions vermischt - nicht gut.
     
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