MySQL: zusätzliches LEFT JOIN und WHERE Klausel in komplexes Query integrieren

tklustig

Erfahrenes Mitglied
Hallo Leute,
Yaslaw, ein SQL Experte par excellence, hatte mir vor einiger Zeit folgendes Query erstellt bzw. erweitert. Das ist für meine SQL Kenntnisse viel zu komplex, als dass ich dadurch irgendetwas verändern könnte. Bedauerlicherweise muss jetzt aber sowohl eine zusätzliche Tabelle gejoint werden, als auch eine WHERE Klausel eingefügt werden. Der zusätzliche JOIN baut sich wie folgt auf(er ist teilweise so schon implementiert; ich poste der Vollständigkeit halber aber den kompletten Bezug:
SQL:
SELECT * FROM product
LEFT JOIN product_property ON product.id = product_property.product_id
LEFT JOIN property_group_option ON property_group_option.id = product_property.property_group_option_id
LEFT JOIN property_group ON property_group.id=property_group_option.property_group_id
LEFt JOIN property_group_translation ON property_group_translation.property_group_id=property_group.id
Letztlich interessieren die zusätzlichen Angaben aus der Tabelle property_group_translation. Da stehen nämlich die Attribute, wohingegen in property_group_option_translation die Attributwerte stehen. Siehe dazu folgendes komplexe Query, zu welchem dann noch eine WHERE Klausel hinzugefügt werden müsste, und zwar in der Form:
SQL:
WHERE product_translation.name LIKE '%ABC%'
oder
SQL:
WHERE renameTransTable.pt_name LIKE '%ABC%'

Jetzt aber das hochkomplexe Query, welches gemäß obiger Anforderungen erweitert werden sollte. Über jede Hilfe bedanke ich mich vorab!

SQL:
SET @languageID='2fbb5fe2e29a4d70aa5854ce7ce3e20b';
-- Atribut Bezeichnungen
WITH attributes AS (
    SELECT product_property.product_id, property_group_option_translation.name AS AttributBez
    FROM  product_property
              LEFT JOIN property_group_option_translation ON property_group_option_translation.property_group_option_id = product_property.property_group_option_id
),
-- Spalte name in der Tabelle product_translation umbenennen
     renameTransTable AS (
         SELECT product_translation.name AS pt_name, product_translation.product_id
         FROM product_translation
         WHERE product_translation.language_id = UNHEX(@languageID)
     ),
-- Daten. Master & Variants
-- Produkt um Attribut und Translation Tabelle ergänzen
     p_data as (
         SELECT product.id, product.product_number, renameTransTable.pt_name AS p_name, product.parent_id, attributes.AttributBez
         FROM product
                  LEFT JOIN renameTransTable ON product.id  = renameTransTable.product_id
                  LEFT JOIN attributes ON product.id = attributes.product_id
     )

-- Master und Variant (beides die gleiche Quelle) kombinieren
SELECT master.id AS master_id, master.product_number AS master_product_number, MIN(master.p_name) AS masterBez,
       variant.id AS variant_id, variant.product_number AS variant_product_number, MIN(variant.p_name) AS variantBez,
       master.AttributBez AS masterAttrBez, variant.AttributBez as variantAttrBez
FROM p_data AS master
         INNER JOIN p_data AS variant ON variant.parent_id = master.id
GROUP BY master.id, variant.id, master.product_number, variant.product_number, master.AttributBez, variant.AttributBez;
 
Zuletzt bearbeitet:
Das kannst du doch direkt in den renameTransTable setzen
SQL:
-- Spalte name in der Tabelle product_translation umbenennen
 renameTransTable AS (
     SELECT product_translation.name AS pt_name, product_translation.product_id
     FROM product_translation
     WHERE product_translation.language_id = UNHEX(@languageID)
        AND product_translation.name LIKE '%ABC%'
 ),
 
Gut. Vielen Dank! Die WHERE Klausel packe ich dort rein, aber wie JOINE ich die Tabelle? Die vorige steht im WITH Teil. Mit WITH kenne ich mich so gar nicht aus....
 
Zuletzt bearbeitet:
Zum WITH. Damit kannst d dein SQL Schritt für Schritt aufbauen und zusammensetzen. In dienem Fall musst du den ganzen Karsumpel 2 mal machen. Einaml für master und einmla für variant. Mit dem WITH baust du das nur einhnmal zusammen und kannst es dann als master und als variant verwenden.
Die verscheidenen Quellen in einem WITH sind wie ausgelagerte Views.

Mal ein wenig abstahiert
SQL:
WITH 
-- Erste Qulle Erstellen.
view1 AS (select * from table1),
-- Zweite Quelle erstellen, so können auch weitere hinzugefügt werden
view2 AS (select * from table2),
-- dritte Quelle, verwender auch die zweite Quelle, da diese wieter vorne definiert wurde ist sie verfügbar
view3 AS (select * from view2)
-- Das eigenltiche SQL. Jedoch sind Unterabfragen im WITH ausgelagert
select *
from viewi1 left join view3 on view1.linkid = view3.linkid

Und dein Konstrukt vereinfacht zur Übersicht
SQL:
WITH 
attributes AS (select * from product_property left join property_group_option_translation),
renameTransTable AS (select * from product_translation where language),
p_data AS (select * from product left join renameTransTable left join attributes)

select *
from p_data as master left join p_data as variant
Also kannst du deinen Wehre in die Quelle renameTransTable setzen, denn genau dort greiffst du auf product_translation zu
SQL:
SET @languageID='2fbb5fe2e29a4d70aa5854ce7ce3e20b';
-- Atribut Bezeichnungen
WITH attributes AS (
    SELECT product_property.product_id, property_group_option_translation.name AS AttributBez
    FROM  product_property
        LEFT JOIN property_group_option_translation ON property_group_option_translation.property_group_option_id = product_property.property_group_option_id
),
-- Spalte name in der Tabelle product_translation umbenennen
 renameTransTable AS (
     SELECT product_translation.name AS pt_name, product_translation.product_id
     FROM product_translation
     WHERE product_translation.language_id = UNHEX(@languageID)
        AND product_translation.name LIKE '%ABC%'
 ),
-- Daten. Master & Variants
-- Produkt um Attribut und Translation Tabelle ergänzen
 p_data as (
     SELECT product.id, product.product_number, renameTransTable.pt_name AS p_name, product.parent_id, attributes.AttributBez
     FROM product
          LEFT JOIN renameTransTable ON product.id  = renameTransTable.product_id
          LEFT JOIN attributes ON product.id = attributes.product_id
 )

-- Master und Variant (beides die gleiche Quelle) kombinieren
SELECT master.id AS master_id, master.product_number AS master_product_number, MIN(master.p_name) AS masterBez,
       variant.id AS variant_id, variant.product_number AS variant_product_number, MIN(variant.p_name) AS variantBez,
       master.AttributBez AS masterAttrBez, variant.AttributBez as variantAttrBez
FROM p_data AS master
         INNER JOIN p_data AS variant ON variant.parent_id = master.id
GROUP BY master.id, variant.id, master.product_number, variant.product_number, master.AttributBez, variant.AttributBez;[/sql]
 
Und wie wird in Deinen Ausführungen jetzt die Tabelle property_group_translation gejoint, so dass nicht nur die Attributwerte, sondern auch die Attribute aufgelistet werden? Indem
Code:
WITH attributes AS (
erweitert wird?
Code:
 renameTransTable AS (
enthält doch weder Attributbezeichungen noch Attributwerte.
 
Zuletzt bearbeitet:
Jeder Teil im With ost eine eigene View. und diese kann nachfolgend wieder als Quelle verwendet werden.
Beid einem Beipiel verwirrt mich der Name bezeichnung#. Aber grundsätzloch glaub ja.
 
Meinen vorigen Kommentar habe ich abgeändert. Sorry. Unklar bleibt, wie die Tabelle property_group_translation gejoint werden soll
 
Habe das jetzt völlig anders wie Du gelöst. Ob sich der Response unterscheidet, muss sich noch zeigen. Solange aber unklar ist, wie ich besagte Tabelle joine, wäre das die unbestätigte Lösung.
SQL:
SET @languageID='2fbb5fe2e29a4d70aa5854ce7ce3e20b';
SELECT
    p.id AS masterproduct_id,p.product_number AS masterproduct_number,pt.name AS masterproduct_name,p.stock AS masterproduct_stock,p.tax_id AS masterproduct_tax_id,
    pv.id AS variantproduct_id,pv.product_number AS variantproduct_number,ptv.name AS variantproduct_name,pv.stock AS variantproduct_stock,pv.tax_id AS variantproduct_tax_id,
    pgt.name AS Attribut,
    pot.name AS Attributwert
FROM
    product AS p 
LEFT JOIN product_translation AS pt 
    ON pt.product_id = p.id
INNER JOIN product AS pv
ON pv.parent_id = p.id
LEFT JOIN product_translation AS ptv 
ON ptv.product_id = pv.id
LEFT JOIN product_property AS pp 
ON pp.product_id = p.id
LEFT JOIN property_group_option AS pgo 
ON pgo.id = pp.property_group_option_id
LEFT JOIN property_group_option_translation AS pot 
ON pot.property_group_option_id = pgo.id
LEFT JOIN property_group AS pg 
ON pg.id = pgo.property_group_id
LEFT JOIN property_group_translation AS pgt 
ON pgt.property_group_id = pg.id
WHERE
pot.language_id = UNHEX(@languageID) AND pgt.language_id = UNHEX(@languageID) AND pt.language_id = UNHEX(@languageID) AND ptv.language_id = UNHEX(@languageID)
(AND ptv.name LIKE '%Tele%'
OR pt.name LIKE '%Tele%')
ORDER BY p.product_number, pv.product_number;
 
Zuletzt bearbeitet:
Wenn ich mir die Kompliziertheit dieser Abfrage und die Inflation an Joins ansehe, frage ich mich, ob sich das mit modernen Mitteln vereinfachen ließe, damit es leichter zu pflegen und zu erweitern ist.
Siehe hier:
Aber um das beurteilen zu können, müsste man die genaue Struktur der Tabellen und deren Verknüpfungen kennen.

Edit: Hier ist u. U. schon Potenzial für eine Vereinfachung:
Letztlich interessieren die zusätzlichen Angaben aus der Tabelle property_group_translation. Da stehen nämlich die Attribute, wohingegen in property_group_option_translation die Attributwerte stehen.
Attribute und Attributwerte - gehören die nicht zusammen? Müssen die in getrennten Tabellen stehen?
 
Zuletzt bearbeitet:
Attribute und Attributwerte - gehören die nicht zusammen? Müssen die in getrennten Tabellen stehen?
Denk an "Fremdsprachen"-Übersetzung. Und OP's Tabellen haben ja sogar "translation" im Namen.

Wobei du recht hast: Attribut und Attributwert gehören in eine Tabelle.
Wobei OP wahrscheinlich die "Attribut-Bezeichnung" (!!) aus einer separaten Tabelle holt.
 
Zurück