2012-09-29 148 views
2

我有一個產品ID列表,我想知道哪些訂單包含所有這些產品。 Orders表的結構是這樣的:如何查找列表/集是否包含在另一個列表中

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 

究竟有沒有前途,或者我應該去閱讀托爾金? :)另外,出於好奇,如果不可能在MySQL中,是否有任何其他數據庫具有此功能?

+0

這stringly類型編程:'(222555)的GROUP_CONCAT(產品) ',並且通常不鼓勵。使用適當的基於集合的方法 –

+0

不鼓勵?我不認爲這會執行,更不用說產生任何有意義的結果。我相信我很清楚這是一個'幻想'的問題,只是爲了讓我更好地瞭解我在找什麼。 – Amati

+0

是的,我知道它甚至不是一個有效的構造。我明白了,我只是認爲你真的想用group_concat ;-) –

回答

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中的這一點變得簡單。

+0

感謝您的答覆和鏈接。井井有條! – Amati

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子句中的某個位置。

+0

謝謝,很高興知道我是否有更復雜的案例。 – Amati

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 

現場測試:http://www.sqlfiddle.com/#!2/fa1ad/5

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) 
+0

我相信你誤解了我的問題。請查看其他答案。 – Amati

+0

這列出了包含所有產品的訂單。如果這不是你想要的,你應該改述你的問題,恕我直言。 (我不認爲我需要閱讀答案才能找出問題的含義) – wildplasser

+0

我有一個*列表*的產品。每次運行查詢時,該列表都可能會更改。你的查詢似乎在做什麼是檢查訂單表* *全*產品表。你當然不需要閱讀任何東西。這只是你花時間回答這個問題,並認爲我會指出爲什麼它不正確。不管怎樣,謝謝你。 – Amati

相關問題