MySql - Daten mit mehreren Bedingungen holen

KingJamez

NGBler
Registriert
18 Juli 2013
Beiträge
440
Ich möchte eine kleine Produkt Sortierung schreiben, die auf mehrere Werte reagieren soll,
am ende sollen nur Produkte ausgespuckt werden auf die auch alle Filter zutreffen.

Meine Datenbank Tabellen sehen so aus:

[src=text]# products

id | name | etc....
1 | pro1 | ..
2 | pro2 | ..
3 | pro3 | ..



# product_attributes (attribut gruppen)

id | name
1 | Farbe
2 | Hersteller
3 | Breite
4 | Tiefe

# product_attributes_options (attribut optionen)

id | name | attribute_id
1 | blau | 1
2 | grün | 1
3 | 5cm | 3
4 | 7cm | 3
5 | Nokia | 2

# poducts_2_options

product_id | option_id
1 | 1
1 | 3
1 | 5
1 | 2
2 | 1
2 | 3
2 | 5
2 | 2[/src]


Ich übergebe mit get- parametern die attribute und dazu passenden optionen
bsp.:
[src=text]?Hersteller=Nokia&Farbe=blau&Tiefe=5cm[/src]
und möchte am ende nur Produkt 1 zurück bekommen, das enthält zwar zusätzlich auch noch die Farbe grün, spielt ja aber in dem Moment keine große rolle.

Die Tabelle "products" enthält meine eigentlichen Produkte,
Die Tabelle "product_2_options" enthält den bezug zwischen Option und Produkt
Die Tabelle "product_attributes_options" enthält nur die Optionen und die bezüge auf deren eltern attribute
Die Tabelle "product_attributes" enthält nur die Gruppen namen.

Mit einzelnen parametern kann ich relativ leicht mit WHERE filtern. Meine ersten versuche waren dann mit "WHERE in (...)" zu filtern, dann bekomme ich aber zu viele werte zurück, alle wo einer von beiden vorkommt.
Gibt es eine andere Lösung? Ist es überhaupt in einem Query möglich?

Ich habe schon einige Versuche, komme aber leider nicht zum ziel, unten ein paar meiner versuche
[src=text]
// geht nur mit einem match
SELECT
p2o.product_id,
p2o.id,
p2o.option_id,
opt.id AS opt_id,
opt.name AS opt_name,
opt.attribute_id,
attr.id AS attribute_id,
attr.name AS attribute_name

FROM
gc_products_2_attributes_options p2o

JOIN
gc_products_attributes_options opt
ON
opt.id = p2o.option_id

JOIN
gc_products_attributes attr
ON
attr.id = opt.attribute_id

WHERE
attr.name = 'Hersteller'
AND
opt.name = 'Nokia'



SELECT
opt.name,
opt.id,
opt.attribute_id,
prod2opt.id AS prod_opt_id,
prod2opt.product_id AS prod_opt_prod_id,
prod2opt.option_id AS prod_opt_opt_id,
attr.id,
attr.name

FROM
gc_products_attributes_options opt

LEFT JOIN
gc_products_2_attributes_options prod2opt
ON
prod2opt.option_id = opt.id
AND
opt.name = 'Nokia'

LEFT JOIN
gc_products_attributes attr
ON
attr.id = opt.attribute_id
AND
attr.name = 'Hersteller'

// kein ergebnis :(
SELECT
opt.name,
opt.id,
opt.attribute_id,
prod2opt.id AS prod_opt_id,
prod2opt.product_id AS prod_opt_prod_id,
prod2opt.option_id AS prod_opt_opt_id,
attr.id,
attr.name

FROM
gc_products_attributes_options opt

INNER JOIN
gc_products_2_attributes_options prod2opt
ON
prod2opt.option_id = opt.id
AND
opt.name = 'Nokia'
AND
opt.name = '5cm'


INNER JOIN
gc_products_attributes attr
ON
attr.id = opt.attribute_id
AND
attr.name = 'Hersteller'
AND
attr.name = 'Breite'


[/src]

Perspektivisch habe ich überlegt nur die Produkt id´s zu holen und die Produkt- Daten dann mit einer Schleife aus meinem Produkt-Model zu holen.
 
Eine Sache: In Deinen Testdaten ist das Attribut Tiefe doch für gar kein Produkt vergeben, oder sehe ich das falsch?

Du musst doch nur noch mit den Produkten joinen und dann nach [kw]products.id[/kw] gruppieren und dann überprüfen, ob noch immer alle angeforderten Attribute vorhanden sind. Oder übersehe ich etwas? Ich hab das mal realisiert, indem ich einfach überprüfe, ob die gefilterten Elemente noch die zusammen gruppierten Attributsnamen enthalten:

[src=mysql]SELECT products.id

FROM `products`

JOIN `gc_products_2_attributes_options`
ON gc_products_2_attributes_options.product_id = products.id

JOIN `gc_products_attributes_options`
ON gc_products_attributes_options.id = gc_products_2_attributes_options.option_id

JOIN `gc_products_attributes`
ON gc_products_attributes.id = gc_products_attributes_options.attribute_id

WHERE (gc_products_attributes.name = 'Hersteller' AND gc_products_attributes_options.name = 'Nokia')
OR (gc_products_attributes.name = 'Farbe' AND gc_products_attributes_options.name = 'grün')
OR (gc_products_attributes.name = 'Breite' AND gc_products_attributes_options.name = '5cm')

GROUP BY products.id

HAVING GROUP_CONCAT(gc_products_attributes.name ORDER BY gc_products_attributes.name) = 'Breite,Farbe,Hersteller'[/src]

Aber mal ein ganz anderer Ansatz: Verwendest Du ein Framework? Kann es nicht sein, dass das vielleicht schon eine fertige Filter-Option für solche Zwecke bereitstellt?
 
  • Thread Starter Thread Starter
  • #3
Vielen dank für die Hilfe, so hat´s geklappt. Nein ich verwende kein Framework was mir diese Funktion bietet.
Nein du siehst es richtig, in meinen Testdaten ist das Attribut "tiefe" nicht vergeben, nicht jedes Produkt enthält auch immer alle Attribute- Gruppen.
 
Zurück
Oben