SQL Server:多对多

发布于 2025-01-07 11:30:17 字数 1088 浏览 3 评论 0原文

我有一个多对多关系:OrdersOrderProductsProducts。我需要一个查询,为我提供并非所有订单中但已订购的产品列表。

______________________
|      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 的查询。

另请记住,虽然产品不多,但实时数据库中有数十万个订单。

I have a many to many relationship, Orders, OrderProducts, and Products. I need a query that gives me a list of products that are NOT in ALL orders, but has been ordered.

______________________
|      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    |

In the provided example, notice that product 1 is in all orders and product 6 is not ordered at all.

I need a query that returns Products 2, 3, 4, and 5.

Also keep in mind that while there aren't many products, there are a few hundred thousand orders in the live database.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你没皮卡萌 2025-01-14 11:30:17
SELECT PRODUCTID 
FROM ORDERPRODUCTS  
GROUP BY PRODUCTID 
HAVING COUNT(DISTINCT OrderID) < (SELECT COUNT(*) FROM ORDERS )
SELECT PRODUCTID 
FROM ORDERPRODUCTS  
GROUP BY PRODUCTID 
HAVING COUNT(DISTINCT OrderID) < (SELECT COUNT(*) FROM ORDERS )
虚拟世界 2025-01-14 11:30:17

现在是星期六晚上,所以这可能不是最优雅的,但这里有一个尝试:

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
  )
);

It's Saturday night, so this is probably not the most elegant, but here's one try:

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
  )
);
撧情箌佬 2025-01-14 11:30:17
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
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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文