Daten aus zwei Tabellen zusammenführen

voumi

Benutzer
Beiträge
11
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>
 
Werbung:
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?
 
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.)
 
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:
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=*#
 
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.
 
Mein Problem - ok.... eines meiner Probleme - ist, dass ich keine "Spalten" mit Namen, Vornamen etc. habe.

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)
 
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
 
Werbung:
Zurück
Oben