我有三个表:产品,PRO_FAB和Fabrics。 Products表有Product_ID和Name,PRO_FAB有PRO_FAB_ID,Product_ID和Fabric_ID,Fabrics有Fabric_ID和Name。他们是这样的:
Products.Product_ID --- PRO_FAB.Product_ID <-> PRO_FAB.Product_ID --- Fabrics.Fabric_ID.
所以它基本上是一种m:n的关系。我正在尝试创建一个查询,该查询将列出由Fabrics表中的所有结构制成的产品。我尝试过使用HAVING,CONTAINS和其他方法,但似乎都没有用,或者至少我不知道如何使用它们。感谢您的帮助。
答案 0 :(得分:2)
DECLARE @TotalFabrics int
SELECT @TotalFabrics = count(*) FROM dbo.Fabrics
SELECT p.Name
FROM Products p
INNER JOIN PRO_FAB pf ON pf.Product_ID = p.Product_ID
INNER JOIN Fabrics f ON f.Fabric_ID = pf.Fabric_ID
GROUP BY p.Name
HAVING COUNT(f.Fabric_ID) = @TotalFabrics
如果您正在寻找使用ALL面料的产品,这应该可行。有兴趣看看人们会想出什么其他方法。
如果需要,你也可以用子查询替换@TotalFabrics,但我认为这更整洁。
答案 1 :(得分:1)
正如Dmitri正确指出的那样,以下查询获得的产品包含任何结构,而不是所有结构(我读得太快,没有花时间去理解它)。
SELECT Fabrics.Name as FabricName, Products.Name as ProductName
FROM Fabrics
INNER JOIN PRO_FAB pf on Fabrics.FabricID = pf.FabricID
INNER JOIN Products on Products.ProductID = pf.ProductID
ORDER BY FabricName, ProductName
Dmitri的解决方案优雅且易于理解(我确信它的性能更好,所以我已经给它一个投票),但我想到了另一个可行的解决方案(我相信还有更多)
;with cte as
(
SELECT Products.Product_ID, Fabrics.Fabric_ID
FROM Fabrics CROSS JOIN Products
)
Select Products.Name
FROM Products
WHERE Product_ID
NOT IN(SELECT cte.Product_ID
FROM cte
LEFT OUTER JOIN PRO_FAB
ON cte.Fabric_ID = PRO_FAB.Fabric_ID
AND PRO_FAB.Product_ID = cte.Product_ID
WHERE PRO_FAB_ID IS NULL)
如果您的SQL版本不支持公用表表达式,则可以使用内联子查询。