我有包含列表,类别的表格以及将它们相互映射的表格。因此,列表可以放在多个类别中。如下所示:
listings table
id
title
etc
categories table
id
category_name
etc
map table
listing_id
category_id
当我需要获取单个类别中列表的所有信息时(在本例中为id为18的类别),以下工作正常:
SELECT *
FROM (`listings`, `map`)
WHERE `map`.`category_id` = 18
AND map.listing_id = listings.id
我的问题是如何进行类似类型的查询,但现在我需要找到两个类别内的不同列表。例如,如果我只需要返回category_id = 18 AND category_id = 20中的那些不同列表,该怎么办?这需要某种类型的加入吗?
答案 0 :(得分:2)
是的,你会想要(另一个)加入。我认为以下应该这样做:
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`
另一个版本,受到Germ建议的启发,但这个版本有效(请注意,为了清晰起见,我将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;
您可以通过获取所需的所有行然后过滤它们来消除该子选择。请注意,此解决方案假定映射表中的行是唯一的(应该是这种情况,因为应在listing_id
和category_id
上定义PK。)
答案 1 :(得分:1)
这应该有效
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)
答案 2 :(得分:0)
这个怎么样......
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)