Anfängerprobleme

Schnurze

Benutzer
Beiträge
16
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?
 
Werbung:
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 ...
 
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?
 
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....
 
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.
 
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.
 
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.....
 
Werbung:
Zurück
Oben