Sql server 2008 SQL Server:多对多
我有多对多关系、订单、订单产品和产品。我需要一个查询,给我一个不是在所有订单,但已订购的产品列表Sql server 2008 SQL Server:多对多,sql-server-2008,tsql,many-to-many,Sql Server 2008,Tsql,Many To Many,我有多对多关系、订单、订单产品和产品。我需要一个查询,给我一个不是在所有订单,但已订购的产品列表 ______________________ | ORDERS | _______________________ | OrderID | OrderDate | | 1 | 1/2/2012 | | 2 | 1/3/2012 | | 3 | 1/4/2012 | | 4 | 1/5/2012 | | 5
______________________
| ORDERS |
_______________________
| OrderID | OrderDate |
| 1 | 1/2/2012 |
| 2 | 1/3/2012 |
| 3 | 1/4/2012 |
| 4 | 1/5/2012 |
| 5 | 1/6/2012 |
______________________
| ORDERPRODUCTS |
_______________________
| OrderID | PRODUCTID |
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
| 2 | 4 |
| 3 | 1 |
| 3 | 5 |
| 4 | 1 |
| 5 | 1 |
__________________________
| PRODUCTS |
__________________________
| PRODUCTID | PRODUCTNAME |
| 1 | Widget 1 |
| 2 | Widget 2 |
| 3 | Widget 3 |
| 4 | Widget 4 |
| 5 | Widget 5 |
| 6 | Widget 6 |
在提供的示例中,请注意,产品1在所有订单中,而产品6根本没有订购
我需要一个返回产品2、3、4和5的查询
还请记住,虽然产品不多,但live数据库中有几十万份订单。这是周六晚上,所以这可能不是最优雅的,但这里有一个尝试:
SELECT PRODUCTID
FROM ORDERPRODUCTS
GROUP BY PRODUCTID
HAVING COUNT(DISTINCT OrderID) < (SELECT COUNT(*) FROM ORDERS )
DECLARE @OrderProducts TABLE(OrderID INT, ProductID INT);
DECLARE @Products TABLE(ProductID INT, ProductName VARCHAR(32));
INSERT @Products VALUES
(1,'Widget 1'),(2,'Widget 2'),
(3,'Widget 3'),(4,'Widget 4'),
(5,'Widget 5'),(6,'Widget 6');
INSERT @OrderProducts VALUES
(1,1),(1,2),(2,1),(2,2),(2,3),
(2,4),(3,1),(3,5),(4,1),(5,1);
SELECT p.ProductID, p.ProductName
FROM @Products AS p
WHERE EXISTS -- had been ordered at least once
(
SELECT 1 FROM @OrderProducts
WHERE ProductID = p.ProductID
)
AND EXISTS -- at least one order does NOT include it
(
SELECT 1 FROM @OrderProducts AS o
WHERE NOT EXISTS
(
SELECT 1 FROM @OrderProducts AS o2
WHERE o2.OrderID = o.OrderID
AND o2.ProductID = p.ProductID
)
);
另一方面,在这个网站上格式化表格数据很糟糕……TBH我不会花时间格式化表格。在@Aaron的回答中提供示例DDL和插入脚本要有用得多。如果您发布代码、XML或数据示例,只需在文本编辑器中突出显示这些行,然后单击编辑器工具栏上的“代码示例”按钮{},以很好地格式化和语法突出显示它@Darthg8r请注意,我的查询几乎有一半是提供实际的创建表和插入脚本,正如Martin在上面指出的,这些脚本比转储文本有用得多。哦,我知道。我根本没有反对你的质询。我期待一个比他提供的复杂得多的查询。@Darthg8r-Aaron的可能比你问题中提到的基数更有效。你需要两个都试试看。我的场景比你看到的场景复杂。我将尝试这两种方法,并让你们知道它们从性能的角度来看结果如何。我的计划稍微好一点,但我仍然会+1表示优雅。我一直在尝试使用INTERSECT/EXCEPT获得一个更优雅的版本,但Non in any order让我难以置信。
SELECT
DISTINCT
PossibleOrderProducts.PRODUCTID
FROM
(
SELECT
Orders.ORDERID,
Products.PRODUCTID
FROM
ORDERS Orders
CROSS JOIN
(
SELECT DISTINCT PRODUCTID FROM ORDERPRODUCTS
) Products
) PossibleOrderProducts
LEFT JOIN ORDERPRODUCTS ActualOrderProducts ON
ActualOrderProducts.ORDERID = PossibleOrderProducts.ORDERID
AND ActualOrderProducts.PRODUCTID = PossibleOrderProducts.PRODUCTID
WHERE
ActualOrderProducts.ORDERID IS NULL