Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 2008 SQL Server:多对多_Sql Server 2008_Tsql_Many To Many - Fatal编程技术网

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