SQL N 到无关系 Table

SQL N To No Releationship Table

我有 3 个 table 这个名字

供应商:商店供应商信息

SupplierID Name
1 Supplier 1
2 Supplier 2
3 Supplier 3
4 Supplier 4

产品:商店产品信息

ProductID Name
1 Product 1
2 Product 2
3 Product 3
4 Product 4
5 Product 5

SupplierProduct : 对于供应商可以供应的商店产品

ProductID SupplierID
2 1
3 1
4 1
2 2
3 2
4 2
3 3
4 3
1 4
2 4
4 4

我想编写一个查询来获取一堆产品 ID 和 return 具有所有这些产品 ID 的供应商 ID(N:N 关系)例如获取产品 ID 2,3 和 return 只是供应商 ID 1,2

您可以按如下方式使用intersect

select distinct SupplierID 
from SupplierProduct
where ProductID = 2
intersect
select SupplierID 
from SupplierProduct
where ProductID = 3

Fiddle

这是一道 Relational Division With Remainder 的题,有多个除数。

首先,为了能够很好地解决这个问题,您需要以表格形式输入数据。您可以为此使用 table 变量或 Table 值参数。

有很多解决方案。这是一个常见的:

  • 将输入数据加入 SupplierProduct table。在您的情况下,您只需要 Supplier 数据,因此在子查询中执行此操作。
  • 将其分组并检查计数是否与输入的总计数相匹配
DECLARE @ProductInput TABLE (ProductID int);
INSERT @ProductInput (ProductID) VALUES (2),(3);

SELECT *
FROM Supplier s
WHERE (SELECT COUNT(*)
    FROM SupplierProduct sp
    JOIN @ProductInput pi ON pi.ProductID = sp.ProductID
    WHERE sp.SupplierID = s.SupplierID
) = (SELECT COUNT(*) FROM @ProductInput)
;

db<>fiddle

另一个常见的解决方案是双 NOT EXISTS。这验证了 没有 输入 没有 匹配。它通常被认为效率较低。

DECLARE @ProductInput TABLE (ProductID int);
INSERT @ProductInput (ProductID) VALUES (2),(3);

SELECT *
FROM Supplier s
WHERE NOT EXISTS (SELECT 1
    FROM @ProductInput pi
    WHERE NOT EXISTS (SELECT 1
        FROM SupplierProduct sp
        WHERE pi.ProductID = sp.ProductID
          AND sp.SupplierID = s.SupplierID
    )
);

试试这个:

DECLARE     @Supplier TABLE (SupplierID int, Name varchar(50));
INSERT INTO @Supplier VALUES
        (1, 'Supplier 1')
    ,   (2, 'Supplier 2')
    ,   (3, 'Supplier 3')
    ,   (4, 'Supplier 4')
;
DECLARE     @Product TABLE (ProductID int, Name varchar(50));
INSERT INTO @Product VALUES
        (1, 'Product 1')
    ,   (2, 'Product 2')
    ,   (3, 'Product 3')
    ,   (4, 'Product 4')
    ,   (5, 'Product 5')
;

DECLARE     @SupplierProduct TABLE (ProductID int, SupplierID int);
INSERT INTO @SupplierProduct VALUES
        (2, 1)
    ,   (3, 1)
    ,   (4, 1)
    ,   (2, 2)
    ,   (3, 2)
    ,   (4, 2)
    ,   (3, 3)
    ,   (4, 3)
    ,   (1, 4)
    ,   (2, 4)
    ,   (4, 4)
;

DECLARE     @ProductSelection   TABLE   (ProductID int)
INSERT INTO @ProductSelection
    SELECT
        ProductID
    FROM @Product
    WHERE   1=1
        --  AND ProductID IN (2, 3) --   returns Suppliers 1, 2
        --  AND ProductID IN (3, 4) --   returns Suppliers 1, 2, 3
            AND ProductID IN (2, 4) --   returns Suppliers 1, 2, 4
;

WITH SupplierList AS
    (
        SELECT
                RowNo = ROW_NUMBER() OVER (PARTITION BY SP.SupplierID ORDER BY SP.SupplierID)
            ,   S.SupplierID
        FROM    @SupplierProduct    SP
        JOIN    @ProductSelection   P   ON  P.ProductID     = SP.ProductID
        JOIN    @Supplier           S   ON  S.SupplierID    = SP.SupplierID
    )

SELECT  
        SupplierID
FROM    SupplierList
WHERE   RowNo   = (SELECT SUM(1) FROM @ProductSelection)