Комплексный поиск по тегам - PullRequest
0 голосов
/ 01 апреля 2012

У меня сейчас проблема с поиском товаров по тегам:

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 голосов
/ 01 апреля 2012

Это работает:

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

Я использовал псевдонимы, чтобы сделать код более читабельным.Также вам не нужны внешние объединения, так как вам не нужны записи, которые не совпадают в соединяемых таблицах.

0 голосов
/ 01 апреля 2012

Очевидно, тег не может быть 'energy' или 'energies' и , в то же время, 'light' или 'lights'. Таким образом, условие в вашем запросе должно состоять только из OR s:

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
0 голосов
/ 01 апреля 2012

попробуйте следующий запрос:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...