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

Anfängerprobleme

Dieses Thema im Forum "MySQL und MariaDB" wurde erstellt von Schnurze, 21 Oktober 2018.

  1. Schnurze

    Schnurze Benutzer

    Hi,

    bin neu hier und relativ neu bei MariaDB und habe natürlich ein Problem, naja wohl eher ein Problemchen...
    Also folgendes:
    Tabelle data mit vier Spalten ID, USER_ID, FIELD_ID, VALUE.
    ID gibt jeder Zeile einen festen Wert,
    USER_ID ist 11 mal der gleiche Wert, der jeweils einer FIELD_ID zugeordnet ist, VALUE ist der eigentliche Wert. Das wiederhohlt sich fortlaufend. Also jeder Kunde (USER_ID) besteht aus 11 Einträgen (FIELD_ID von 1 bis 11) deren Werte wie Anschrift, Tel. etc in VALUE stehen.
    Mein Problem: Wie bekomme ich eine Abfrage hin, bei der Kd.Nr. Vornahme, Nachnahme, Telefon in einer Zeile stehen?
    Mein Ansatz:
    SELECT `USER_ID` `Kd. Nr.` , (select `VALUE` where `FIELD_ID` = 8) as Vorname, (select `VALUE` where `FIELD_ID` = 9) as Nachname, (select `VALUE` where `FIELD_ID` = 6) as Telefon FROM `data` where `USER_ID` = 967
    Liefert mir zwar die benötigten Daten, aber halt in 11 Zeilen.
    Sorry für so ein kleines Anfängerproblem, aber könntet ihr mir trotzdem helfen?
     
  2. akretschmer

    akretschmer Datenbank-Guru

    Code:
    test=# create table schnurze(id serial primary key, user_id int, field_id int, value text);
    CREATE TABLE
    test=*# insert into schnurze (user_id, field_id, value) values (1, 1, 'Max');
    INSERT 0 1
    test=*# insert into schnurze (user_id, field_id, value) values (1, 2, 'Mustermann');
    INSERT 0 1
    test=*# insert into schnurze (user_id, field_id, value) values (1, 3, 'Berlin');
    INSERT 0 1
    test=*# insert into schnurze (user_id, field_id, value) values (2, 1, 'Susi');
    INSERT 0 1
    test=*# insert into schnurze (user_id, field_id, value) values (2, 2, 'Sorglos');
    INSERT 0 1
    test=*# insert into schnurze (user_id, field_id, value) values (2, 3, 'hinterm Mond');
    INSERT 0 1
    test=*# select user_id, string_agg(case when field_id=1 then value else null end,'') as vorname, string_agg(case when field_id=2 then value else null end,'') as nachname, string_agg(case when field_id= 3 then value else null end, '') as wohnort from schnurze group by user_id;
     user_id | vorname |  nachname  |   wohnort   
    ---------+---------+------------+--------------
           1 | Max     | Mustermann | Berlin
           2 | Susi    | Sorglos    | hinterm Mond
    (2 rows)
    
    test=*#
    
    Das ist jetzt PostgreSQL, MySAL hat wohl eine ähnliche Funktion. Ich würde allerdings dazu eher JSON nehmen. Ich zeig dann noch ein Beispiel, später ...
     
  3. akretschmer

    akretschmer Datenbank-Guru

    so, wie versprochen, hier eine Lösung mit JSONB. Zuerst einmal wandeln wir die Tabelle um:

    Code:
    test=*# create table schnurze_jsonb as select user_id, jsonb_object_agg(field_id, value) x from schnurze group by user_id;
    SELECT 2
    test=*# select * from schnurze_jsonb ;
     user_id |                         x                         
    ---------+----------------------------------------------------
           2 | {"1": "Susi", "2": "Sorglos", "3": "hinterm Mond"}
           1 | {"1": "Max", "2": "Mustermann", "3": "Berlin"}
    (2 rows)
    
    Zugriff nun wie folgt:

    Code:
    test=*# select user_id, x->>'1' as vorname, x->>'2' as nachname, x->>'3' as wohnort from schnurze_jsonb ;
     user_id | vorname |  nachname  |   wohnort   
    ---------+---------+------------+--------------
           2 | Susi    | Sorglos    | hinterm Mond
           1 | Max     | Mustermann | Berlin
    (2 rows)
    
    Angenehmer, oder?
     
  4. Schnurze

    Schnurze Benutzer

    Vielen Dank. Das war die Lösung.
    SELECT `USER_ID` `Kd. Nr.` , GROUP_CONCAT(case when field_id=8 then value else null end,'') as Vorname, GROUP_CONCAT(case when field_id=9 then value else null end,'') as Nachname, GROUP_CONCAT(case when field_id=6 then value else null end,'') as Telefon FROM `data` where `USER_ID` = 967 GROUP BY `USER_ID`

    ups- hab den 2. Post noch gar nicht gesehen.
     
  5. Schnurze

    Schnurze Benutzer

    Die 2. Lösung ist natürlich wesentlich eleganter. Allerdings verändert sich die data Tabelle fortlaufend (neue Kunden rein, alte raus) und da über Tabelle viele weitere Abfragen, Cronjobs etc. laufen, kann ich die auch nicht so einfach umwandeln, bzw. müsste sie bei jeder Abfrage neu umwandeln....
     
  6. akretschmer

    akretschmer Datenbank-Guru

    ja, is klar. Die Idee ist ja auch, das gleich so anzulegen, als JSONB-Feld, und von Anfang an damit (also mit JSONB) zu arbeiten.
     
  7. Schnurze

    Schnurze Benutzer

    Doch noch ein Problem:
    SELECT `po` `Kdnr`, `size` `Größe`, `lagerort` `Lagerort`, DATE_FORMAT (`eingang`, '%d.%m.') `Datum`, GROUP_CONCAT(case when field_id=8 then value else null end, '') as Vorname, GROUP_CONCAT(case when field_id=9 then value else null end, '') as Name, GROUP_CONCAT(case whenfield_id=6 then value else null end, '') as Telefon FROM `pakete`, `data` WHERE `eingang` <= DATE_SUB(CURDATE(), INTERVAL 90 DAY) AND `ausgang` IS NULL AND `po` = `USER_ID` GROUP BY `USER_ID` ORDER BY `lagerort` ASC, `po` ASC
    funktioniert so weit, also die Abfrage welche Warengrößen wo eingelagert sind nach einer bestimmten Zeit. Allerdings halt nur bei einem Lagerort. Bei mehreren Lagerorten wird nur der erste angezeigt, allerdings erhöht sich halt für jeden weiteren der Vorname, Nachname, Telefon jeweils um 1, also z.B. wird aus Max halt Max, Max etc.
     
  8. akretschmer

    akretschmer Datenbank-Guru

    alle Spalten müssen entweder aggregiert (group_concat ist eine Aggregation) oder gruppiert sein. Dies ist bei Dir nicht der Fall. Daß das logisch falsch ist, erkennt MySQL nicht und liefert statt dessen ein falsches Resultat.

    Merke: MySQL ist doof.
     
  9. Schnurze

    Schnurze Benutzer

    Schön oder auch nicht, aber wie löse ich mein Problem?
    Es sind ja auch 2 verschiedene Tabellen. Müssen dabei auch alle Spalten in beiden Tabellen aggegiert oder gruppiert sein?
    GROUP_CONCAT(`size`) AS `Größe` führt nur zu ner Menge gleicher Größen, fein säuberlich mit nem Komma getrennt.....
     
  10. akretschmer

    akretschmer Datenbank-Guru

    alle Spalten, die im Resultat sind, müssen entweder ... oder ....
     

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