复杂的标签搜索

时间:2012-04-01 13:50:23

标签: mysql sql

我目前在使用代码搜索产品时遇到问题:

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

我需要构建一个查询来获取标记为(能量)和(灯光或灯光)的产品

到目前为止,这不起作用:

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

更新了查询。 注意:我需要查询来搜索标记的单数和复数时态,如上面的查询中所示。

3 个答案:

答案 0 :(得分:0)

尝试以下查询:

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

答案 1 :(得分:0)

这有效:

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');

我使用了别名来使代码更具可读性。此外,您不需要外连接,因为您不希望连接表中的记录不匹配。

答案 2 :(得分:0)

显然,标记不能同时是'energy''energies' 'light''lights'。因此,查询中的条件必须仅包含OR

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

或者,当然,您可以使用IN

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

另一件事是,如何检查产品是否同时具有前两个中的至少一个和另外两个中的至少一个。我可能会使用这样的HAVING子句来完成它:

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