1

I have two tables:

products

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

So product 1 has two sizes: 1, 2. Product 2 has two sizes: 1, 3. Product 3 has one size: 3.

What I want to do is build a query that pulls back the products that have both size 1 and size 3 (i.e. Product 2). I can easily create a query that pulls back the products that have both sizes 1 AND 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

When I run this query, I get back Product 1, Product 2, and Product 3.

Just to reiterate, I'd like to only get back Product 2. I've tried using the HAVING clause, messing around with $id IN GROUP_CONCAT(...) but I haven't been able to get anything to work. Thanks in advance, guys.

4

4 回答 4

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 
于 2013-06-14T03:49:49.697 回答
1

COUNT由于您需要 1 和 3,因此您需要size_idsIN (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;

在这里查看演示。请让我知道这对你有没有用。

于 2013-06-14T02:52:37.790 回答
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;
于 2013-06-14T04:54:37.293 回答
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);

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

于 2013-06-14T04:33:40.573 回答