2013-03-02 43 views
3

我有簡單許多一對多表PRODUCT_CATEGORY關係(MSSQL 2008 R2):SQL獲得行在「= ALL」風格

CREATE TABLE #Product_Category (ProductId int, CategoryId int); 
go 
INSERT INTO #Product_Category (ProductId, CategoryId) 
VALUES (1, 200); 
go 
INSERT INTO #Product_Category (ProductId, CategoryId) 
VALUES (2, 200); 
go 
INSERT INTO #Product_Category (ProductId, CategoryId) 
VALUES (2, 400); 
go 
INSERT INTO #Product_Category (ProductId, CategoryId) 
VALUES (3, 300); 
go 
INSERT INTO #Product_Category (ProductId, CategoryId) 
VALUES (2, 300); 
go 
DROP TABLE #Product_Category 

如何選擇產品編號與條件:類別ID = 200 CategoryId = 300 and CategoryId = 400?

查詢示例(SQL下面不工作):

SELECT ProductId FROM #Product_Category 
WHERE CategoryId = ALL (select 200 union select 300 union select 400) 

我期待的結果:產品編號= 2

回答

4
select PC.ProductId 
from #Product_Category as PC 
where PC.CategoryId in (200, 300, 400) 
group by PC.ProductId 
having count(distinct PC.CategoryId) = 3 
1

更新: 它仍然是醜陋,但它的工作:

SELECT DISTINCT master.ProductId 
FROM #Product_Category master 
JOIN (
    SELECT ProductId, 
      cat200 = max(case when CategoryId=200 then 1 else 0 end), 
      cat300 = max(case when CategoryId=300 then 1 else 0 end), 
      cat400 = max(case when CategoryId=400 then 1 else 0 end) 
    FROM #Product_Category 
    GROUP BY ProductId 
) sub ON sub.ProductId = master.ProductId 
WHERE cat200=1 
    and cat300=1 
    AND cat400=1 
+0

查詢值:1,2,2,3,2 – 2013-03-02 05:28:54

+0

我正在啓動一臺服務器以進行測試 – 2013-03-02 05:30:24

+0

@Alexander:已發佈解決方案。即使更醜陋,但它的工作原理。現在我將看到如何用更現代的語法來表達它。 – 2013-03-02 05:42:11

1

試試這個

SELECT a.ProductId 
    FROM Product_Category as a, 
     Product_Category as b, 
     Product_Category as c 
     WHERE a.CategoryId = 200 
      And b.`CategoryId` = 300 
      And c.`CategoryId` = 400 
      And a.`ProductId` = b.`ProductId` 
      And b.`ProductId` = c.`ProductId` 

更多像500和600

SELECT a.ProductId 
    FROM Product_Category as a, 
     Product_Category as b, 
     Product_Category as c, 
     Product_Category as d, 
     Product_Category as e, 
     WHERE a.CategoryId = 200 
      And b.`CategoryId` = 300 
      And c.`CategoryId` = 400 
      And d.`CategoryId` = 500 
      And e.`CategoryId` = 600 
      And a.`ProductId` = b.`ProductId` 
      And b.`ProductId` = c.`ProductId` 
      And c.`ProductId` = d.`ProductId` 
      And d.`ProductId` = e.`ProductId` 

檢查現場演示http://sqlfiddle.com/#!2/8965e/1/0

+0

Coudl你發佈代碼,以便它是可讀的,而不是滾動頁面?我甚至無法將其粘貼到我的srver中。 – 2013-03-02 05:42:54

+0

@pieter geerkens是肯定的人現在檢查 – 2013-03-02 05:45:06

+0

它返回27行'2',這可以通過添加一個DISTINCT來減少,但似乎相當於創建許多重複的記錄wasateful。 – 2013-03-02 05:47:45

1

這裏我使用的是熱膨脹係數,但你可以使用表變量或東西的category_filter不同。

with category_filter as (
    select * from (values (200), (300), (400)) as v(id) 
) 
select distinct ProductId 
from #Product_Category 
join category_filter 
    on (#Product_Category.CategoryId = category_filter.id) 
group by ProductId 
having COUNT(distinct CategoryId) = (select COUNT(*) from category_filter) 
0

而且醜陋的解決方案:)

WITH category_filter1(CategoryId) AS (
    SELECT * FROM (VALUES (200), (300), (400)) tmp1(tmp2) 
) 
SELECT p.ProductId 
FROM (
    SELECT ProductId, 
     CASE WHEN CategoryId IN (SELECT CategoryId FROM category_filter1) THEN 1 ELSE 0 END f 
    FROM #Product_Category 
    ) p 
GROUP BY p.ProductId, p.f 
HAVING COUNT(*) = (SELECT COUNT(*) FROM category_filter1); 
0

您可以使用值如表源,並檢查它們在使用WHERE子句NOT EXISTS和EXCEPT運營商

SELECT * 
FROM #Product_Category p 
WHERE NOT EXISTS (              
        SELECT Match 
        FROM (VALUES(200), 
           (300), 
           (400)) 
        x(Match) 
        EXCEPT 
        SELECT CategoryId 
        FROM #Product_Category p2 
        WHERE p.ProductID = p2.ProductID 
       ) 

上演示SQLFiddle

0
WITH L AS (
SELECT * 
    FROM (VALUES (200),(300),(400)) AS T(CategoryId) 
) 
SELECT ProductId 
    FROM Product_Category P 
INNER JOIN L 
    ON L.CategoryId = P.CategoryId 
GROUP BY ProductId 
HAVING COUNT(1) = (SELECT Count(1) FROM L) 
; 

如果您打算使用TVP,那麼WITH消失。