使用group by时联接表上的多个条件

时间:2013-06-14 02:48:18

标签: mysql sql join group-by

我有两张桌子:

产品

id    name
1     Product 1
2     Product 2
3     Product 3

products_sizes

id    size_id    product_id
1     1          1
2     2          1
3     1          2
4     3          2
5     3          3

因此产品1有两种尺寸:1,2。产品2有两种尺寸:1,3。产品3有一种尺寸:3。

我想要做的是构建一个查询,回收同时具有1号和3号尺寸的产品(即产品2)。我可以轻松创建一个查询,以回收两个大小为1和3的产品:

select `products`.id, `products_sizes`.`size_id`
from `products` inner join `products_sizes` on `products`.`id` = `products_sizes`.`product_id`
where products_sizes.size_id IN (1, 3)
group by products.id

当我运行此查询时,我会返回产品1,产品2和产品3。

重申一下,我只想回到产品2.我已经尝试过使用HAVING子句,弄乱了$ ID IN GROUP_CONCAT(...),但是我无法得到任何东西工作。先谢谢你们。

4 个答案:

答案 0 :(得分:1)

由于您同时需要1和3,因此您需要COUNT size_id IN (1, 3)并且要求结果为2:

SELECT p.id AS id, p.name AS name
FROM   products p, products_sizes s
WHERE  p.id = s.product_id AND s.size_id IN (1, 3)
GROUP  BY s.product_id
HAVING COUNT(DISTINCT s.size_id) = 2;

查看demo here。让我知道它是否适合你。

答案 1 :(得分:1)

如果group_concat的工作方式与PostgreSQL中的相同,那么这个可能适用于MySQL:

select 
  product_id 
from products
left join ( select group_concat(cast(id as char(5)), ',') as agg1 from sz where id in (1, 3) group by size_id ) as qagg1 on 1=1
left join ( select products_sizes.product_id product_id, group_concat(cast(products_sizes.size_id as char(5)), ',') agg2 from sz where products_sizes.size_id IN (1, 3) group by products_sizes.product_id ) as qagg2 on 1=1
where qagg1.agg1 = qagg2.agg2
group by product_id 

这是在PostgreSQL中测试的原始查询:

select 
  product_id 
from pr
left join ( select string_agg(cast(id as char(5)), ',') as agg1 from sz where id in (1, 3) group by size_id ) as qagg1 on 1=1
left join ( select sz.product_id product_id, string_agg(cast(sz.size_id as char(5)), ',') agg2 from sz where sz.size_id IN (1, 3) group by sz.product_id ) as qagg2 on 1=1
where qagg1.agg1 = qagg2.agg2
group by product_id 

答案 2 :(得分:0)

谈到性能,首先过滤到某个size_id会很不错:

SELECT STRAIGHT_JOIN
x.id, y.size_id AS size_1, z.size_id AS size_2
FROM (
  SELECT * FROM products_sizes
  WHERE size_id = 1
) AS y
INNER JOIN products AS x
  ON (x.id = y.product_id)
INNER JOIN (
  SELECT * FROM products_sizes
  WHERE size_id = 3
) AS z
ON (x.id = z.product_id);

谦虚的建议,用更多的数据进行一些测试(:

答案 3 :(得分:0)

select `products`.id, `products_sizes`.`size_id`
from `products` inner join `products_sizes` on `products`.`id` = `products_sizes`.`product_id`
where products_sizes.size_id IN (1, 3)
group by products.id
having count(distinct `products_sizes`.size_id) = 2;