这是我的模式:
CREATE TABLE SampleProducts
(
ProductId INT,
Name NVARCHAR(20)
)
INSERT INTO SampleProducts
VALUES (1, 'Product 1'), (2, 'Product 2'), (3, 'Product 3'),
(4, 'Product 4')
CREATE TABLE Bundle
(
BundleId INT,
Name NVARCHAR(20)
)
INSERT INTO Bundle
VALUES (1, 'Bundle 1'), (2, 'Bundle 2')
CREATE TABLE BundleProduct
(
BundleId INT,
ProductId INT
)
INSERT INTO BundleProduct
VALUES (1, 1), (1, 2), (2, 3), (2, 4)
CREATE TABLE SaleOrder
(
OrderId INT,
OrderNumber NVARCHAR(20)
)
INSERT INTO SaleOrder
VALUES (1, 'SO0001'), (2, 'SO0002'), (3, 'SO0003')
CREATE TABLE SaleOrderLine
(
OrderLineId INT,
OrderId INT,
ProductId INT
)
INSERT INTO SaleOrderLine
VALUES (1, 1, 1), (2, 1, 2), (3, 2, 1),
(4, 3, 3), (5, 3, 4)
我需要找到客户购买可以组合在一起的产品的订单。例如,在订单SO0001
中,产品1和2已售出,此订单必须在结果中。仅在SO0002
中出售了产品1。SO0003包含来自Bundle2
的产品。这是我需要得到的设定结果:
结果
| OrderId | BundleId |
+---------+----------+
| 1 | 1 |
| 3 | 2 |
如何获得结果?
答案 0 :(得分:1)
此查询将SaleOrderLines与Bundles结合在一起,以计算特定Bundle中包含的每个SaleOrder中不同的产品。如果此数字是该捆绑销售商品的总数,则我们有一个匹配项:
WITH
BundleProductCount (BundleID, ProductCount) AS (
SELECT BundleId, COUNT(ProductId)
FROM BundleProduct
GROUP BY BundleId
),
OrderBundleProductCount (OrderId, BundleId, ProductCount) AS (
SELECT sol.OrderId, bp.BundleId, COUNT(DISTINCT sol.ProductId)
FROM SaleOrderLine sol
INNER JOIN BundleProduct bp ON sol.ProductId = bp.ProductId
GROUP BY sol.OrderId, bp.BundleId
)
SELECT ob.OrderId, ob.BundleId
FROM OrderBundleProductCount ob
INNER JOIN BundleProductCount b ON ob.BundleID = b.BundleID
WHERE ob.ProductCount = b.ProductCount;
已添加
:您自己想出的一个简短版本,尊重以相同顺序多次出现的产品:
SELECT l.OrderId, bp.BundleId
FROM SaleOrderLine l
INNER JOIN BundleProduct bp ON l.ProductId = bp.ProductId
GROUP BY l.OrderId, bp.BundleId
HAVING COUNT(DISTINCT l.ProductId) = (
SELECT COUNT(*)
FROM BundleProduct
WHERE BundleId = bp.BundleId
);
答案 1 :(得分:1)
这是我解决此问题的最佳尝试:
SELECT o.[OrderId], bp.[BundleId]
FROM [SaleOrder] o
INNER JOIN [SaleOrderLine] l ON l.[OrderId] = o.[OrderId]
INNER JOIN [SampleProducts] p ON p.[ProductId] = l.[ProductId]
INNER JOIN [BundleProduct] bp ON bp.[ProductId] = l.[ProductId]
GROUP BY o.[OrderId], bp.[BundleId]
HAVING COUNT(*) = (
SELECT COUNT(*)
FROM [Bundle] b
INNER JOIN [BundleProduct] bp2 ON bp.[BundleId] = b.[BundleId]
WHERE bp2.[BundleId] = bp.[BundleId]
GROUP BY b.[BundleId]
)
首先,我将销售订单行与捆绑产品一起加入,对其进行分组,然后对它们进行计数,然后将其与捆绑中的产品数量进行比较,如果结果相等,则意味着可以创建捆绑。这个想法类似于Wolfgang Kais提出的解决方案,但是没有使用Common Table Expressions
***更新
这是删除不必要的联接的新查询。谢谢@MatBailie
SELECT l.[OrderId], bp.[BundleId]
FROM [SaleOrderLine] l
INNER JOIN [BundleProduct] bp ON bp.[ProductId] = l.[ProductId]
GROUP BY l.[OrderId], bp.[BundleId]
HAVING COUNT(*) = (
SELECT COUNT(*)
FROM [BundleProduct] bp2
WHERE bp2.[BundleId] = bp.[BundleId]
GROUP BY bp2.[BundleId]
)
答案 2 :(得分:0)
Row_Number
是此处的关键功能。查询可以写为:
select distinct
OrderId ,
BundleId
From
(
select SO.OrderId,B.BundleId ,
ROW_NUMBER() OVER(PARTITION BY SO.OrderId ORDER BY SO.OrderId ASC) AS Row#
from SaleOrderLine SOL
join SaleOrder SO on SOL.OrderId = SO.OrderId
join BundleProduct BP on BP.ProductId = SOL.ProductId
join Bundle B on B.BundleId = BP.BundleId
) As Test
where Row# > 1