我有一个产品ID列表,我想知道哪些订单包含所有这些产品。订单表的结构如下:
order_id | product_id
----------------------
1 | 222
1 | 555
2 | 333
显然我可以在PHP中使用一些循环来完成它,但我想知道是否有一种优雅的方法可以在mysql中完成它。 我理想的幻想查询类似于:
SELECT order_id
FROM orders
WHERE (222,555) IN GROUP_CONCAT(product_id)
GROUP BY order_id
有没有希望,还是应该读Tolkien? :)另外,出于好奇,如果在mysql中不可能,是否还有其他具有此功能的数据库?
答案 0 :(得分:3)
你很亲密
SELECT order_id
FROM orders
WHERE product_id in (222,555)
GROUP BY order_id
HAVING COUNT(DISTINCT product_id) = 2
关于关系代数中的“出于好奇心”问题,只需使用division即可实现。 AFAIK没有RDBMS实现了任何扩展,使其在SQL中变得简单。
答案 1 :(得分:1)
我倾向于仅在having子句中进行集合比较:
select order_id
from orders
group by order_id
having sum(case when product_id = 222 then 1 else 0 end) > 0 and
sum(case when product_id = 555 then 1 else 0 end) > 0
这说的是:在订单至少有一个产品222和至少一个产品555的情况下,向我索取所有订单。
我更喜欢这个有两个原因。首先是普遍性。您可以安排更复杂的条件,例如222或555(只需更改“和”和“或”)。或者,333和555或222没有555。
其次,在创建查询时,您只需将条件放在having
子句中的一个位置。
答案 2 :(得分:1)
假设您的数据库已正确规范化,即给定订单上没有重复的产品
Mysqlism:
select order_id
from orders
group by order_id
having sum(product_id in (222,555)) = 2
标准SQL:
select order_id
from orders
group by order_id
having sum(case when product_id in (222,555) then 1 end) = 2
如果有重复:
CREATE TABLE tbl
(`order_id` int, `product_id` int)
;
INSERT INTO tbl
(`order_id`, `product_id`)
VALUES
(1, 222),
(1, 555),
(2, 333),
(1, 555)
;
然后执行此操作:
select order_id
from tbl
group by order_id
having count(distinct case when product_id in (222,555) then product_id end) = 2
答案 3 :(得分:1)
CREATE TABLE orders
( order_id INTEGER NOT NULL
, product_id INTEGER NOT NULL
);
INSERT INTO orders(order_id,product_id) VALUES
(1, 222 ) , (1, 555 ) , (2, 333 )
, (3, 222 ) , (3, 555 ) , (3, 333 ); -- order#3 has all the products
CREATE TABLE products AS (SELECT DISTINCT product_id FROM orders);
SELECT *
FROM orders o1
--
-- There should not exist a product
-- that is not part of our order.
--
WHERE NOT EXISTS (
SELECT *
FROM products pr
WHERE 1=1
-- extra clause: only want producs from a literal list
AND pr.product_id IN (222,555,333)
-- ... that is not part of our order...
AND NOT EXISTS ( SELECT *
FROM orders o2
WHERE o2.product_id = pr.product_id
AND o2.order_id = o1.order_id
)
);
结果:
order_id | product_id
----------+------------
3 | 222
3 | 555
3 | 333
(3 rows)