2013-12-15 35 views
1

我有一個表ProductDeliveryModes爲:獲得產品支持所有交付模式在SQL

ProductId DeliveryId 
P101   D1 
P101   D2 
P101   D3 
P102   D1 
P102   D2 
P102   D3 
P103   D1 

我需要得到支持所有交付模式(D1,D2,D3)的產品。從表中看出產品應該是:P101和P102。

,我形成得到解決的查詢是:

SELECT ProductId 
FROM (SELECT DISTINCT ProductId, 
         DeliveryId 
     FROM ProductDeliveryModes) X 
WHERE X.DeliveryId IN ('D1', 'D2', 'D3') 
GROUP BY ProductId 
HAVING COUNT(*) = 3 

,我在我的解決方案中看到的問題是,一個人應該知道的交付模式總數的計數。我們可以通過從子查詢獲取計數來使計數動態化。

有沒有更好的解決方案?

+2

「更好的解決方案」就什麼?可維護性?效率?如果後者是什麼表定義包括索引?另外還有另一張具有不同交付模式的表格嗎?您可能會發現以下文章有用。 [one](https://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/)[two](http:// weblogs .sqlteam.com/peterl/archive/2010/07/02/Proper-Relational-Division-With-Sets.aspx) –

回答

1

我相信你可以使用DISTINCTCOUNT函數來獲得同樣的結果:

SELECT [ProductID] 
FROM ProductDeliveryModes 
GROUP BY [ProductID] 
HAVING COUNT(DISTINCT [DeliveryId]) = 3 

檢查example

您可以簡單地將不同的遞送計數存儲在變量中並使用它。如果你需要做這在一個單一的查詢,這是可能的方式之一:

WITH CTE (DeliveryCount) AS 
(
    SELECT COUNT(DISTINCT [DeliveryID]) 
    FROM DataSource 
) 
SELECT [ProductID] 
FROM DataSource 
CROSS APPLY CTE 
GROUP BY [ProductID] 
     ,CTE.DeliveryCount 
HAVING COUNT(DISTINCT [DeliveryID]) = DeliveryCount 

example

+1

呵呵,好主意。我打算建議使用一個表變量來存儲不同的DeliveryID,但這樣更好。 :) – Kahn

+0

@Kahn,實際上表變量是很好的選擇,因爲在某些情況下'CTE'可能導致性能問題。 – gotqn

1

你可以使用下面的查詢來獲得更好的性能。

;WITH CTE_Product 
AS 
(
     SELECT DISTINCT ProductID 
     FROM ProductDeliveryModes 
),CTE_Delivery 
AS 
(
     SELECT DISTINCT DeliveryId 
     FROM ProductDeliveryModes 
) 

SELECT * 
FROM CTE_Product C 
WHERE NOT EXISTS 
(
    SELECT 1 
    FROM CTE_Delivery D 
    LEFT JOIN ProductDeliveryModes T ON T.DeliveryId = D.DeliveryId AND T.ProductId=C.ProductId 
    WHERE T.ProductID IS NULL 
) 
1

您可以修改您的查詢只是有點來獲得不同的交付方法實際計數:

SELECT ProductID 
FROM ProductDeliveryModes 
GROUP BY ProductID 
HAVING COUNT(*) = 
    (SELECT COUNT (DISTINCT DeliveryId) FROM ProductDeliveryModes)