MySQL возвращает отличные результаты для нескольких условий - PullRequest
0 голосов
/ 03 декабря 2009

У меня есть таблицы со списками, категориями и таблицами, которые сопоставляют их друг с другом. Таким образом, список может быть размещен в нескольких категориях. Примерно так:

listings table
    id
    title
    etc

categories table
    id
    category_name
    etc

map table
    listing_id
    category_id

Когда мне нужно получить всю информацию для списков в пределах одной категории (в данном случае это категория с идентификатором 18), отлично работает следующее:

SELECT *
FROM (`listings`, `map`)
WHERE `map`.`category_id` = 18
AND map.listing_id = listings.id 

Моя проблема в том, как я могу выполнить запрос аналогичного типа, но теперь мне нужно найти те отдельные списки, которые находятся в двух категориях. Например, что если мне нужно вернуть только те отдельные списки, которые находятся в обоих категориях: category_id = 18 и category_id = 20? Требуется ли для этого какой-либо тип соединения?

Ответы [ 3 ]

2 голосов
/ 03 декабря 2009

Да, вы захотите использовать (другое) соединение. Я думаю, что следующее должно сделать это:

SELECT lst.`id`, lst.<column>, ...
FROM `listings` lst, `map` m, `map` m2
WHERE m.`category_id` = 18 AND m2.`category_id` = 20
AND m.`listing_id` = lst.`id`
AND m2.`listing_id` = lst.`id`

Другая версия, вдохновленная предложениями Джерма, но эта работает (обратите внимание, я заменил id на category_id для ясности):

select l.listing_id
from listings l
join (select m.listing_id, count(*) as cnt from map m where
    m.category_id in (18,20)
    group by m.listing_id) cat_matches
    on cat_matches.listing_id = l.listing_id
where cat_matches.cnt = 2; -- 2 is the number of distinct categories to match

Гадкий, а? И отбор может быть не настолько эффективным ... но:


select l.listing_id
from listings l
join map m on l.listing_id=m.listing_id
where m.category_id in (18,20)
group by l.listing_id
having COUNT(*)=2;

Вы можете исключить этот подвыбор, получив все необходимые вам строки и затем отфильтровав их. Обратите внимание, что это решение предполагает, что линии в таблице карты являются уникальными (что должно быть так, поскольку PK должен быть определен как listing_id, так и category_id).

1 голос
/ 03 декабря 2009

Это должно работать

select * from listings l
join map m on m.listing_id = l.id
join categories c on c.id = m.category_id
where c.id in (18, 20)
0 голосов
/ 03 декабря 2009

Как насчет этого ...

select * from listings l, map m, categories c
where l.id = m.listing_id
and m.category_id = c.id
and (c.id = 18 
or c.id = 20)

или

select * from listings l, map m, categories c
where l.id = m.listing_id
and m.category_id = c.id
and c.id in (18, 20)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...