2015-04-07 147 views
3

我一直在尋找這個,但沒有找到任何特別的東西。SQL ALL IN子句

是否有可能具有像ALL IN一樣的SQL查詢?爲了更好地解釋,這是一個表結構。

Orders table 
OrderItem table (having several columns, but mainly ProductID, OrderID) 
ProductGroup table (several columns, but mainly GroupID and ProductID) 

我想編寫一個查詢,它將選擇屬於特定ProductGroup的所有訂單。所以如果我有一個ID = 10的名爲「XYZ」的組。它有一個ProductID。說產品ID01

訂單來了兩個訂單項目。 ProductID01和ProductID02。要查找所有的訂單在特定的產品組,我可以用一個簡單的SQL像

SELECT bvc_OrderItem.ProductID, bvc_OrderItem.OrderID 
From bvc_OrderItem 
INNER JOIN bvc_Product_Group_Product with (nolock) ON bvc_OrderItem.ProductID = bvc_Product_Group_Product.ProductID 
WHERE bvc_Product_Group_Product.GroupID = 10 

或者,我可以使用IN子句

SELECT bvc_OrderItem.ProductID, bvc_OrderItem.OrderID 
From bvc_OrderItem 
WHERE ProductID IN (
    SELECT ProductID FROM bvc_Product_Group_Product WHERE GroupID=10 
) 

然而,這將返回所有訂單寫其中一個或多個ProductIDs是產品組的一部分。如果所有訂單項都是產品組的一部分,我需要返回訂單行。

所以基本上,我需要一個IN子句,如果IN子句中的所有值都與bvc_OrderItem中的行匹配,那麼這個IN子句將被視爲匹配。

或者如果我們使用Join,那麼只有左側的所有行在相應右表中具有值時,Join纔會成功。

如果我能更簡單地寫出來,我會寫這樣

Select ID FROM Table WHERE ID IN (1, 2, 3, 4) 

,如果表中包含IDS 1,2,3,4的所有行;它應該返回成功。如果這些IN值中的任何一個缺失,它應該返回false並且不應該選擇任何值。

你認爲這是可能的嗎?或者有一個解決方法來做到這一點?

+0

也許你應該改寫你的病情爲「訂單,其中不存在任何行,不屬於組X'? – Arvo

+1

這聽起來像[關係部門](https://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/) –

+0

我不'不明白你在找什麼。有一個或多個項目組成的訂單,每個項目都是一個存在於一個組中的產品。因此,您的聲明「查找特定產品組中的所有訂單...」沒有任何意義。訂單與產品組無關。對於由屬於G組的產品P構成的訂單,您是否想要查看僅由G組產品組成的所有其他訂單?或者您是否希望看到包含G組的任何*產品的所有訂單?你在找什麼? – TommCatt

回答

3

你可以在多種方式,如訂單列表:

SELECT oi.OrderID 
FROM bvc_OrderItem oi JOIN 
    bvc_Product_Group_Product pgp 
    ON oi.ProductID = pgp.ProductId AND 
     pgp.GroupID = 10 
GROUP BY oi.OrderID 
HAVING COUNT(DISTINCT oi.ProductID) = (SELECT COUNT(*) 
             FROM bvc_Product_Group_Product 
             WHERE GroupID = 10 
            ); 

獲取特定產品需要額外join。在大多數情況下,訂單列表更有用。

你的ALL IN語法的問題在於它沒有做你想做的事。您要選擇訂單。語法:

SELECT bvc_OrderItem.ProductID, bvc_OrderItem.OrderID 
From bvc_OrderItem 
WHERE ProductID ALL IN (SELECT ProductID 
         FROM bvc_Product_Group_Product 
         WHERE GroupID = 10 
         ) 

這並不說明你打算爲分組是通過OrderId,而不是一些其他的水平。

不過,更重要的是,SQL語言受關係代數的啓發。 SELECT,JOIN,WHEREGROUP BY的構造直接涉及關係代數基本構造。 ALL IN的概念 - 儘管有時是有用的 - 可以使用更基本的構建塊來表達。

+0

WHERE ProductID ALL IN ......它使用哪個SQL Server版本?我已經在2008年和2008年嘗試過了,但對於他們來說這似乎並不是一個有效的選擇。 –

+0

此外,使用計數分組(DISTINCT oi.Product)的事情,可能無法正常工作。由於產品組可能有100種產品,訂單中可能有兩種或四種產品。我們需要確保訂單項目都是產品組的一部分。因此,如果兩個或所有訂單項都是產品組的一部分,我們會將其視爲匹配項。如果它們中的任何一個不是該組的一部分,我們將其視爲不匹配。謝謝 –

0

您可以通過這個棘手的聲明做:

DECLARE @Items TABLE 
    (
     OrderID INT , 
     ProductID INT 
    ) 
DECLARE @Groups TABLE 
    (
     ProductID INT , 
     GroupID INT 
    ) 

INSERT INTO @Items 
VALUES (1, 1), 
     (1, 2), 
     (2, 1), 
     (3, 3), 
     (3, 4) 

INSERT INTO @Groups 
VALUES (1, 10), 
     (2, 10), 
     (3, 10), 
     (4, 15) 


SELECT OrderID 
FROM @Items i 
GROUP BY OrderID 
HAVING (CASE WHEN 10 = ALL (SELECT gg.GroupID 
           FROM  @Items ii 
             JOIN @Groups gg ON gg.ProductID = ii.ProductID 
           WHERE ii.OrderID = i.OrderID) THEN 1 
       ELSE 0 
      END) = 1 

輸出:

OrderID 
1 
2 

而且(這是更好):

SELECT OrderID 
FROM @Items i 
     JOIN @Groups g ON g.ProductID = i.ProductID 
GROUP BY OrderID 
HAVING MIN(g.GroupID) = 10 
     AND MAX(g.GroupID) = 10 
+0

嗨,謝謝你的回覆。但是,即使一個產品屬於該組,也會返回true。我們需要它,如果所有產品屬於該組。我測試了它,即使One ProductID屬於產品組,它也會返回orderid。如果只有一個項目屬於組,我們需要它不返回OrderID。但只有當所有訂單商品(ProductIds)屬於該組時。 –

+0

@SameersJaved,你說的不對。在我的數據中有2個產品的Order = 3(3,4)3是10組,4是15組。Order = 3不會返回我的查詢。 –