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

Abfrage mehrerer Tabellen mit unbekannter Anzahl in einer Tabelle

Dieses Thema im Forum "MySQL und MariaDB" wurde erstellt von Kurt_S, 9 Dezember 2016.

  1. Kurt_S

    Kurt_S Benutzer

    Hallo zusammen

    Ich bin noch ein ziemlicher Anfänger in SQL und versuche meine Abfragen möglichst mit Hilfe von Bücher und Artikeln im Internet zusammen zu stellen, einfach um das gleich gesagt zu haben.
    Jetzt stehe ich jedoch vor einem Problem, bei dem ich nicht einmal weiss, nach was ich suchen soll. Daher auch der etwas seltsame Titel...


    Ich habe vier Tabellen, category, edition, edition_series und typ. Diese sind wie folgt aufgebaut.

    Code:
    edition            edition_series          typ
    ---------          ------------------        ------------
    id                  id                             id
    name            edition_id                  edition_id
    cat_id           serie_nr                     serie_id
    ...                 ...                      image_name
                                                 ...
    
    Nun brauche ich die edition anhand der cat_id, die anzahl der Serien in einer edition und die Bilder aus der Tabelle Typ, die zu der edition gehören. Dies betrifft meist mehrere editionen, sodass nicht alle edition gleich viele Bilder aus typ zugewiesen werden.

    Bisher bin ich soweit, dass mir alles ausgegeben wird, ausser den Bildern.
    Code:
    SELECT e.id, e.name, e.editiondate, e.earlydate, e.rateduration, COUNT(es.serie_nr) FROM edition AS e
    LEFT JOIN edition_series AS es ON es.edition_id = e.id
    WHERE e.cat_id = '1'
    GROUP BY e.id
    
    Ich weiss einfach nicht, wie ich jetzt die Bilder zusätzlich noch holen soll, sodass diese beispielsweise alle in einem Feld aufgezählt werden. Natürlich könnte ich danach in python jedes Tuple durchgehen und eine weitere Abfrage starten, möchte die aber wenn möglich vermeiden.

    Hoffe ich hab mich einigermassen verständlich ausgedrückt.
    Für Hilfe und Anregungen wäre ich sehr dankbar.

    Besten Grüsse
    Kurt
     
  2. akretschmer

    akretschmer Datenbank-Guru

    Du kannst die aggregieren, in PostgreSQL via array_agg() oder string_agg(), allerdings ist Deine Abfrage logisch falsch, Du aggregierst nach einer Spalte und hast 5 Spalten im Select-Teil, wovon aber nur eine im GROUP BY steht. Alle Datenbanken dieser Welt würden hier einen syntaxfehler sehen, und auch MySQL in seiner aktuellsten Mutation.
     
  3. Kurt_S

    Kurt_S Benutzer

    Das werde ich mir in dem Fall nochmals genauer anschauen müssen.
    Danke erstmal.
     
  4. akretschmer

    akretschmer Datenbank-Guru

    Ähm, falls e.id als PRIMARY KEY definiert ist, würde das so in Ordnung gehen mit Deinem Select. Dann wäre das ein hinreichendes bzw. ausreichendes Kriterium für das GROUP BY. Das kann ich aber nicht erkennen, ob das der Fall ist.

    Code:
    test=# create table edition(id int primary key, name text, cat_id int, editiondate date, earlydate date);
    CREATE TABLE
    test=*# create table edition_series(id int primary key, edition_id int references edition, serie_nr int);
    CREATE TABLE
    test=*# create table typ(id int primary key, edition_id int references edition, serie_id int references edition_series, image_name text);
    CREATE TABLE
    
    test=*# select e.id, e.name, e.editiondate, e.earlydate, count(es.serie_nr), string_agg(t.image_name,',') from edition e left join edition_series es on e.id=es.edition_id left join typ t on t.edition_id=e.id where e.cat_id = 1 group by e.id;
     id | name | editiondate | earlydate | count | string_agg
    ----+------+-------------+-----------+-------+------------
    (0 Zeilen)
    
    Aber:

    Code:
    test=*# create table edition2(id int, name text, cat_id int, editiondate date, earlydate date);
    CREATE TABLE
    test=*# select e.id, e.name, e.editiondate, e.earlydate, count(es.serie_nr), string_agg(t.image_name,',') from edition2 e left join edition_series es on e.id=es.edition_id left join typ t on t.edition_id=e.id where e.cat_id = 1 group by e.id;
    FEHLER:  Spalte »e.name« muss in der GROUP-BY-Klausel erscheinen oder in einer Aggregatfunktion verwendet werden
    ZEILE 1: select e.id, e.name, e.editiondate, e.earlydate, count(es.se...
    
     
  5. Kurt_S

    Kurt_S Benutzer

    Du hast recht, das hatte ich nicht geschrieben. e.id ist ein Primary Key, desshalb hats wohl auch funktioniert. Hab das mal getestet mit einem Feld das kein Primary Key ist, dann funktionierts auch nicht. Ist gut zu wissen, sonst wär ich sonst mal darüber gestolpert.

    Jetzt sieht das ganze so aus, GROUP_CONCAT ist, so wie ich das verstehe, das äquivalent zu array_agg(). Wusste dank dir nach was ich suchen muss :)
    Code:
    SELECT e.id, e.name, e.editiondate, e.earlydate, COUNT(es.serie_nr), GROUP_CONCAT(t.image_name) FROM edition e
    LEFT JOIN edition_series es ON e.id=es.edition_id
    LEFT JOIN typ t ON t.edition_id=e.id
    WHERE e.cat_id = 1
    GROUP BY  e.id
    
    Jetzt hab ich dafür das Problem, dass der Count auf die Serien_Nr. nicht mehr richtig funktioniert bzw. nicht so wie ich es gerne hätte.
    Ich habe z.B. zwei Serien und 4 Bilder, da gibt der Cound 8 aus. Bei einer Serie und 6 Bildern gibt er 6 aus. Als würde er alle Bildfelder durchlaufen und hochzählen.

    Das Problem hat sicher damit zu tun, dass ich noch zu wenig verstehe wie das genau funktioniert.

    Besten Dank für deine bisherigen Tips, hast mich einen riesigen Schritt vorwärts gebracht...
     
  6. akretschmer

    akretschmer Datenbank-Guru

    Code:
    test=*# select * from edition;
     id | name  | cat_id | editiondate | earlydate  
    ----+-------+--------+-------------+------------
      1 | edi 1 |  1 | 2016-12-09  | 2016-12-09
      2 | edi 2 |  1 | 2016-12-09  | 2016-12-09
      3 | edi 3 |  2 | 2016-12-09  | 2016-12-09
    (3 Zeilen)
    
    test=*# select * from edition_series ;
     id | edition_id | serie_nr
    ----+------------+----------
      1 |  1 |  1
      2 |  1 |  2
      3 |  2 |  3
      4 |  2 |  1
      5 |  2 |  2
    (5 Zeilen)
    
    test=*# select * from typ ;
     id | edition_id | serie_id | image_name
    ----+------------+----------+------------
      1 |  1 |  1 | bild 1
      2 |  1 |  2 | bild 2
      3 |  2 |  1 | bild 21
      4 |  2 |  2 | bild 22
    (4 Zeilen)
    
    test=*# select e.id, e.name, e.editiondate, e.earlydate, count(distinct es.serie_nr), string_agg(distinct t.image_name,',') from edition e left join edition_series es on e.id=es.edition_id left join typ t on t.edition_id=e.id where e.cat_id = 1 group by e.id,es.edition_id;
     id | name  | editiondate | earlydate  | count |  string_agg   
    ----+-------+-------------+------------+-------+-----------------
      1 | edi 1 | 2016-12-09  | 2016-12-09 |  2 | bild 1,bild 2
      2 | edi 2 | 2016-12-09  | 2016-12-09 |  3 | bild 21,bild 22
    (2 Zeilen)
    
    test=*#
    
    Hilft das?
     
  7. Kurt_S

    Kurt_S Benutzer

    Oh ja das hilft... Du bist genial. Ich seh schon, ich hab noch einiges zu lernen...
    Vielen Dank für deine Hilfe.
     
    akretschmer gefällt das.
  8. akretschmer

    akretschmer Datenbank-Guru

    es kann übrigens recht schnell passieren, daß Dir meine Tipps nicht weiterhelfen, weil ich PostgreSQL nutze, was deutlich mehr Features als MySQL hat.
     
  9. Kurt_S

    Kurt_S Benutzer

    Das habe ich beim suchen und lesen jetzt auch gesehen. Aber diesesmal hast mir sehr geholfen. Meist findet man trotzdem einen Weg, sobald man mal weiss wonach man suchen muss.
    Ev. wird das ganze ja mal auf PostgreSQL portiert, war schon einmal angedacht.
     
    akretschmer gefällt das.
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