2012-04-01 8 views
0

Im Moment habe ich ein Problem mit der Suche Produkten mit Tags haben:Komplexe Suche nach Tags

Products 
id name 
1 lightbulb 

Tags 
id name 
1 energy 
2 light 
3 lights 

Tagships 
id taggable_id tag_id 
1 1   1 
1 1   2 
1 1   3 

Ich brauche eine Abfrage zu erstellen, die Produkte zu erhalten, die als (Energie) markiert ist und (Licht oder Beleuchtung)

Bisher funktioniert das nicht:

SELECT ..<snipped>.. 
FROM `products` 
LEFT OUTER JOIN `tagships` 
ON (`products`.`id` = `tagships`.`taggable_id`) 
LEFT OUTER JOIN `tags` 
ON (`tags`.`id` = `tagships`.`tag_id`) 
WHERE ((tags.name = 'energy' OR tags.name = 'energies') 
AND (tags.name = 'light' OR tags.name = 'lights')) 
GROUP BY products.id 
HAVING COUNT(tagships.tag_id) <= 2 
ORDER BY products.updated_at DESC 

die Abfrage aktualisiert. Hinweis: Ich brauche die Abfrage, um nach Singular- und Pluralform des Tags zu suchen, wie in der obigen Abfrage zu sehen ist.

+0

ich meine Antwort aktualisiert haben, um Platz für Plurale Ihrer Suchbegriffe zu finden. Leider hat Englisch zu viele Pluralformen, um es algorithmisch zu tun; Sie müssen nur alle Begriffe auflisten, die Sie finden möchten. Vielleicht möchten Sie eine Liste möglicher Suchbegriffe mit dem entsprechenden Plural haben, wenn Sie Ihren Suchanfragen einen Mehrwert hinzufügen möchten? –

Antwort

0

versuchen die folgende Abfrage:

SELECT ..<snipped>.. 
FROM `products` 
LEFT OUTER JOIN `tagships` 
ON (`products`.`id` = `tagships`.`taggable_id` 
AND `tagships`.`taggable_type` = 'Product') 
LEFT OUTER JOIN `tags` 
ON (`tags`.`id` = `tagships`.`tag_id`) 
WHERE ((tags.name = 'energy' OR tags.name = 'energies') 
OR (tags.name = 'light' OR tags.name = 'lights')) 
GROUP BY products.id 
HAVING COUNT(tagships.tag_id) <= 2 
ORDER BY products.updated_at DESC 
+0

Ich brauche sie tatsächlich Singular UND Plural. Ich kann nicht "Energie%" eingeben. –

+0

dann nur die obige Abfrage, müssen Sie 'OR' setzen – Vikram

+0

Sorr, aber ich sehe nicht, welche Änderung Sie in Ihrer Abfrage getan haben. Ich kann 'Like' nicht verwenden und wenn ich '(tags.name wie 'energy%') oder (tags.name wie 'light%)' durch '((tags.name =' energy 'ODER tags.name = 'Energien') AND (tags.name = 'light' ODER tags.name = 'lights')) ', würde es zurück zu meiner Abfrage, die nicht funktioniert. –

0

Dies funktioniert:

SELECT distinct p.id, p.name 
FROM products as p 
join tagships as ts on ts.product_id = p.id 
join tags as t on t.id = ts.tag_id 
where t.name in ('energy', 'energies', 'light', 'lights'); 

ich Aliase verwendet habe den Code besser lesbar zu machen. Außerdem möchten Sie keine äußeren Joins, da Sie keine Datensätze möchten, die in den verknüpften Tabellen nicht übereinstimmen.

0

Offenbar kann ein Tag nicht 'energy' oder 'energies'und sein, zur gleichen Zeit, 'light' oder 'lights'. So muss die Bedingung in der Abfrage von OR bestehen s nur:

WHERE t.name = 'energy' 
    OR t.name = 'energies' 
    OR t.name = 'light' 
    OR t.name = 'lights' 

Alternativ kann natürlich können Sie IN verwenden:

WHERE t.name IN ('energy', 'energies', 'light', 'lights') 

Eine andere Sache ist, wie Sie überprüfen können, dass ein Produkt sowohl hat mindestens eines der ersten zwei und mindestens eines der beiden anderen. Ich tun würde, ist es wahrscheinlich eine HAVING Klausel wie folgt aus:

HAVING COUNT(CASE WHEN t.name IN ('energy', 'energies') THEN 1 END) > 0 
    AND COUNT(CASE WHEN t.name IN ('light', 'lights') THEN 1 END) > 0 
+0

Sie haben mit der ersten Aussage Recht. aber ich kann deine ersten beiden Abfragen nicht verwenden. Ich werde deine letzte Anfrage versuchen. –

+0

Nicht sicher, was Sie mit Ihrem * nicht verwenden können *. Ich hätte mich vielleicht nicht klar genug ausgedrückt: Die 'HAVING'-Klausel in meiner Antwort soll mit einer meiner' WHERE'-Klauseln verwendet werden, nicht nur als Alternative zu ihnen. –