MySQL Abfrage über 2 Tabellen
Hallo,
irgendwie steh ich mächtig auf dem Schlauch (liegts am Montag?).
Ich habe 2 MySQL-Tabellen:
Tab "Produkt" ... | id | name | ...
Tab "Komponenten ... | id | id_produkt | nummer | name | ...
In der Tab "Produkt" stehen die Produkte.
In der Tab "Komponenten" stehen die einzelnen Teile, aus denen ein Produkt besteht.
Jetzt möchte ich alle Produkte angezeigt bekommen, die mindestens aus bestimmten Komponenten/Teilen bestehen.
Bsp.:
- Produkt EINS besteht aus den Teilen mit der "nummer" 123, 456, 789, 134, 188
- Produkt ZWEI besteht aus den Teilen mit der "nummer" 123, 456, 677, 777, 223, 334
- Produkt DREI besteht aus den Teilen mit der "nummer" 123, 456, 781, 134, 333, 431
Ich suche nach den Produkten, die alle mindestens aus den Teilen mit der "nummer" 123, 456 und 134 bestehen.
Somit sollte das Ergebnis die Produkte EINS und DREI sein.
Wie setze ich die MySQL-Abfrage richtig an?
Steh da gerade voll aufm dem Schlauch.
Danke schon mal im Voraus.
irgendwie steh ich mächtig auf dem Schlauch (liegts am Montag?).
Ich habe 2 MySQL-Tabellen:
Tab "Produkt" ... | id | name | ...
Tab "Komponenten ... | id | id_produkt | nummer | name | ...
In der Tab "Produkt" stehen die Produkte.
In der Tab "Komponenten" stehen die einzelnen Teile, aus denen ein Produkt besteht.
Jetzt möchte ich alle Produkte angezeigt bekommen, die mindestens aus bestimmten Komponenten/Teilen bestehen.
Bsp.:
- Produkt EINS besteht aus den Teilen mit der "nummer" 123, 456, 789, 134, 188
- Produkt ZWEI besteht aus den Teilen mit der "nummer" 123, 456, 677, 777, 223, 334
- Produkt DREI besteht aus den Teilen mit der "nummer" 123, 456, 781, 134, 333, 431
Ich suche nach den Produkten, die alle mindestens aus den Teilen mit der "nummer" 123, 456 und 134 bestehen.
Somit sollte das Ergebnis die Produkte EINS und DREI sein.
Wie setze ich die MySQL-Abfrage richtig an?
Steh da gerade voll aufm dem Schlauch.
Danke schon mal im Voraus.
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 2730153038
Url: https://administrator.de/forum/mysql-abfrage-ueber-2-tabellen-2730153038.html
Ausgedruckt am: 22.12.2024 um 20:12 Uhr
17 Kommentare
Neuester Kommentar
Zitat von @derSESO:
"tabelle1 as x" ist soweit korrekt.
Aber, mit der Abfrage bekomme auch die Produkte, wo nur eines der 3 Teile drin ist.
Ich brauche aber nur die Produkte, wo alle 3 Teile drin sind.
"tabelle1 as x" ist soweit korrekt.
Aber, mit der Abfrage bekomme auch die Produkte, wo nur eines der 3 Teile drin ist.
Ich brauche aber nur die Produkte, wo alle 3 Teile drin sind.
Wie wäre es mit ein AND statt OR für die Bediengungen?
Bin kein Experte aber ein Versuch schadet nicht
Zitat von @derSESO:
Schon versucht ... da findet er gar nix.
Hab es jetzt mal so gemacht ... zumindest stimmen die Ergebnisse - aber vlt. geht es effektiver.
Schon versucht ... da findet er gar nix.
Hab es jetzt mal so gemacht ... zumindest stimmen die Ergebnisse - aber vlt. geht es effektiver.
SELECT DISTINCT P.id
FROM Produkt AS P
WHERE (SELECT id FROM Komponenten WHERE id_produkt = P.id AND nummer = '123') AND
(SELECT id FROM Komponenten WHERE id_produkt = P.id AND nummer = '456') AND
(SELECT id FROM Komponenten WHERE id_produkt = P.id AND nummer = '134')
Habe wieder keine Ahnung aber einfach so gedacht und was geschrieben.
Wie wäre es mit
SELECT DISTINCT P.id
FROM Produkt AS P, Komponenten
WHERE id_produkt = P.id AND (p.nummer = 123 AND p.nummer = 456 AND p.nummer = 134)
ich würde es so machen, aber ich habe kein MySQL ...
postgres=# select * from komponenten ;
produkt | komponente
---------+------------
1 | 123
1 | 456
1 | 789
1 | 134
1 | 188
2 | 123
2 | 456
2 | 677
2 | 777
2 | 223
2 | 334
3 | 123
3 | 456
3 | 781
3 | 134
3 | 333
3 | 431
(17 rows)
postgres=# select produkt, array_agg(komponente) from komponenten group by produkt having array_agg(komponente) @> array[123,456,134]; ;
produkt | array_agg
---------+---------------------------
3 | {123,456,781,134,333,431}
1 | {123,456,789,134,188}
(2 rows)
postgres=#
es gäbe noch weitere Wege, aber ich bin mir nicht einmal sicher, ob die Tabellenstruktur richtig normalisiert ist oder ob da Pfusch am Bau betrieben wurde...
Zitat von @akretschmer:
... wenn man das für 3Cent etwas weiter denkt, dann wäre 123 = 456 = 134. Merste jetzt selber, oder?
WHERE Komponenten.id_produkt = 123 AND Komponenten.id_produkt = 456 AND Komponenten.id_produkt = 134;
... wenn man das für 3Cent etwas weiter denkt, dann wäre 123 = 456 = 134. Merste jetzt selber, oder?
sieht so aus
Ich hab das mal mit MSSQL gemacht:
Datentabellen habe ich jetzt im WITH-Teil, die können natürlich raus. Für die gesuchte Zusammensetzung habe ich eine Tabelle werteliste genommen, das kann natürlich auch ein Produkt aus der vorhandenen Tabelle sein.
WITH produkt(id,[name]) AS (
SELECT 1,'EINS' UNION ALL
SELECT 2,'ZWEI' UNION ALL
SELECT 3,'DREI'
), komponenten(id,id_produkt,nummer) AS (
SELECT 0,1,123 UNION ALL
SELECT 1,1,456 UNION ALL
SELECT 2,1,789 UNION ALL
SELECT 3,1,134 UNION ALL
SELECT 4,1,188 UNION ALL
SELECT 5,2,123 UNION ALL
SELECT 6,2,456 UNION ALL
SELECT 7,2,677 UNION ALL
SELECT 8,2,777 UNION ALL
SELECT 9,2,223 UNION ALL
SELECT 10,2,334 UNION ALL
SELECT 11,3,123 UNION ALL
SELECT 12,3,456 UNION ALL
SELECT 13,3,781 UNION ALL
SELECT 14,3,134 UNION ALL
SELECT 15,3,333 UNION ALL
SELECT 16,3,431
), werteliste(nummer) AS (
SELECT 123 UNION ALL
SELECT 456 UNION ALL
SELECT 134
)
SELECT k.id_produkt
FROM werteliste w
INNER JOIN komponenten k
ON w.nummer = k.nummer
GROUP BY k.id_produkt
HAVING count(*) = ( SELECT count(*) FROM werteliste )
Hallo derSESO,
grundsätzlich liegst Du mit Deiner Abfrage wohl richtig. Bei SQL Server würde es heißen:
Ob es ein "exists" bei MySQL gibt, weiß ich nicht, aber so wie Du die Abfrage formuliert hast, scheint der Effekt derselbe zu sein, wenn Dein Ergebnis stimmt.
Alternative wäre noch:
Gruß, Mad Max
grundsätzlich liegst Du mit Deiner Abfrage wohl richtig. Bei SQL Server würde es heißen:
SELECT P.id
FROM Produkt AS P
WHERE exists (SELECT id FROM Komponenten WHERE id_produkt = P.id AND nummer = '123') AND
exists (SELECT id FROM Komponenten WHERE id_produkt = P.id AND nummer = '456') AND
exists (SELECT id FROM Komponenten WHERE id_produkt = P.id AND nummer = '134')
Ob es ein "exists" bei MySQL gibt, weiß ich nicht, aber so wie Du die Abfrage formuliert hast, scheint der Effekt derselbe zu sein, wenn Dein Ergebnis stimmt.
Alternative wäre noch:
SELECT DISTINCT P.id
FROM Produkt AS P
join Komponenten as k1 on k1.id_produkt = P.id AND k1.nummer = '123'
join Komponenten as k2 on k2.id_produkt = P.id AND k2.nummer = '456'
join Komponenten as k3 on k3.id_produkt = P.id AND k3.nummer = '134'
Gruß, Mad Max
Zitat von @MadMax:
Hallo derSESO,
grundsätzlich liegst Du mit Deiner Abfrage wohl richtig. Bei SQL Server würde es heißen:
Ob es ein "exists" bei MySQL gibt, weiß ich nicht, aber so wie Du die Abfrage formuliert hast, scheint der Effekt derselbe zu sein, wenn Dein Ergebnis stimmt.
Alternative wäre noch:
Gruß, Mad Max
Hallo derSESO,
grundsätzlich liegst Du mit Deiner Abfrage wohl richtig. Bei SQL Server würde es heißen:
SELECT P.id
FROM Produkt AS P
WHERE exists (SELECT id FROM Komponenten WHERE id_produkt = P.id AND nummer = '123') AND
exists (SELECT id FROM Komponenten WHERE id_produkt = P.id AND nummer = '456') AND
exists (SELECT id FROM Komponenten WHERE id_produkt = P.id AND nummer = '134')
Ob es ein "exists" bei MySQL gibt, weiß ich nicht, aber so wie Du die Abfrage formuliert hast, scheint der Effekt derselbe zu sein, wenn Dein Ergebnis stimmt.
Alternative wäre noch:
SELECT DISTINCT P.id
FROM Produkt AS P
join Komponenten as k1 on k1.id_produkt = P.id AND k1.nummer = '123'
join Komponenten as k2 on k2.id_produkt = P.id AND k2.nummer = '456'
join Komponenten as k3 on k3.id_produkt = P.id AND k3.nummer = '134'
Gruß, Mad Max
Beide Lösungen sind bei zunehmender Anzahl von zu prüfenden Komponenten zunehmend ###e. Stelle Dir mal die Anzahl im 4-stelligen Bereich vor: tausende EXISTS oder tausende JOIN. Pest oder Cholera?
Oder lieber, als weitere Variante zur schon gezeigten:
postgres=# select produkt, count(komponente) from komponenten where komponente in (123,456,134) group by produkt having count(produkt) = 3;
produkt | count
---------+-------
3 | 3
1 | 3
(2 rows)
Offensichtlich viel einfacher zu erweitern...
exists ist normalerweise recht schnell, vor allem in Verbindung mit einem Index. Da sehe ich das geringere Problem. Die joins sind natürlich so eine Sache ...
Dein erster Vorschlag hatte aber auch ein Problem: ob MySQL die Syntax von PostgreSQL beherrscht ist die Frage.
Dein letzter Vorschlag sieht aber sehr gut aus. Allerdings würde ich empfehlen, "count (distinct nummer)" zu verwenden. Jedenfalls, wenn kein eindeutiger Index auf id_produkt und nummer existiert und MySQL das beherrscht.
Gruß, Mad Max
Dein erster Vorschlag hatte aber auch ein Problem: ob MySQL die Syntax von PostgreSQL beherrscht ist die Frage.
Dein letzter Vorschlag sieht aber sehr gut aus. Allerdings würde ich empfehlen, "count (distinct nummer)" zu verwenden. Jedenfalls, wenn kein eindeutiger Index auf id_produkt und nummer existiert und MySQL das beherrscht.
Gruß, Mad Max