棘手的SQL查询 - 寻找替代供应商(关系部门)

时间:2013-01-14 12:39:36

标签: sql relational-division

这是我从书中得到的一个问题(不记得哪一个),它是这样的:

你有三张桌子:

  • 供应商supId, name
  • 产品prodId, name
  • 广告资源supId, prodId

您需要通过一个查询查找供应商X所拥有的所有产品(或更多)的所有供应商(假设供应商X是具有supId=1的供应商)。

(因此,如果供应商1的库存中有香蕉和苹果,则需要找到所有至少带有香蕉和苹果的供应商)

您只能使用标准SQL(包括连接)。

显然这是一个已知的问题/问题,你应该看看这个问题: How to filter SQL results in a has-many-through relation (优秀的解决方案和分析)

2 个答案:

答案 0 :(得分:6)

该问题称为relational division

一种解决方案是双重否定。您可以选择供应商X未交付产品的所有供应商,这些供应商不是由他们提供的:

select  distinct other_supplier.SupID
from    Inventory other_supplier
where   not exists
        (
        select  *
        from    Inventory supplier_X
        where   supplier_X.supId = 1 -- For supplier X
                and not exists
                (        
                select  *
                from    Inventory other_product
                where   other_supplier.supId = other_product.Supid
                        and supplier_X.prodId = other_product.prodId
                )
        )

Live example at SQL Fiddle.

答案 1 :(得分:1)

我认为此解决方案使用标准SQL,但参数定义除外。

DECLARE @supplierX int = 4

SELECT 
  [s].[supid],
  [s].[name]
FROM [Inventory] [i1]
INNER JOIN [Inventory] [i2] ON [i1].[prodid] = [i2].[prodid]
INNER JOIN [Supplier] [s] ON [i1].[supid] = [s].[supid]
WHERE
  [i1].[supid] <> @supplierX
  AND [i2].[supid] = @supplierX
GROUP BY 
  [s].[supid],
  [s].[name]
HAVING 
  COUNT(*) >= (SELECT COUNT(*) FROM [Inventory] [i3] WHERE [i3].[supid] = @supplierX)

找到小提琴here

上述查询的细分:

  • 确定供应商X在其库存中的产品数量(count(*)
  • 确定其他供应商与supplierX共享的产品(prodid join
  • 确保共享产品的数量高于或等于supplierX在其库存中的产品数量(HAVING COUNT() >= ...