自连接或递归查询以获取计数
Self join or Recursive query to get the count
我需要按行分组,其中分组集中的一个值存在于另一行中。就像我有下面的 table
| OrderID | ProductID |
| 123 | A |
| 123 | B |
| 223 | B |
| 223 | C |
| 323 | C |
| 323 | D |
| 423 | E |
我需要以下内容。我一直在想一些方法,但无法到达任何地方。有什么帮助吗?
|ProductId | NoOfOrders |
| A|B|C|D | 3 |
| E | 1 |
给你。这从基于匹配产品的简单分组开始,然后使用循环递归地将事物分组在一起,直到它找不到更多的合并来做:
CREATE TABLE #data
(
OrderId INT,
ProductId CHAR(1)
);
INSERT INTO #data (OrderId, ProductId)
VALUES (123,'A'),
(123,'B'),
(223,'B'),
(223,'C'),
(323,'C'),
(323,'D'),
(423,'E');
CREATE TABLE #data2
(
OrderId INT,
ProductId CHAR(1),
Grp INT
);
WITH cte AS
(
SELECT OrderId,
ProductId,
DENSE_RANK() OVER (ORDER BY ProductId) r
FROM #data
)
INSERT INTO #data2(OrderId, ProductId, Grp)
SELECT cte.OrderId,
cte.ProductId,
r
FROM cte
DECLARE @updates INT = 1;
WHILE @updates > 0
BEGIN
-- join groups where there is a lower numbered group that it connects to
UPDATE a
SET Grp = b.Grp
FROM #data2 a
INNER JOIN #data2 b ON b.OrderId = a.OrderId
OR b.ProductId = a.ProductId
WHERE a.Grp > b.Grp
-- end when we have done nothing this cycle
SET @updates = @@ROWCOUNT
END
SELECT
STUFF((SELECT DISTINCT '|'+ ProductId
FROM #data2
WHERE grp = o.grp
FOR xml path('')
), 1, 1, '') AS Products,
COUNT(DISTINCT o.OrderId) AS NumOrders
FROM #data2 o
GROUP BY grp
我需要按行分组,其中分组集中的一个值存在于另一行中。就像我有下面的 table
| OrderID | ProductID |
| 123 | A |
| 123 | B |
| 223 | B |
| 223 | C |
| 323 | C |
| 323 | D |
| 423 | E |
我需要以下内容。我一直在想一些方法,但无法到达任何地方。有什么帮助吗?
|ProductId | NoOfOrders |
| A|B|C|D | 3 |
| E | 1 |
给你。这从基于匹配产品的简单分组开始,然后使用循环递归地将事物分组在一起,直到它找不到更多的合并来做:
CREATE TABLE #data
(
OrderId INT,
ProductId CHAR(1)
);
INSERT INTO #data (OrderId, ProductId)
VALUES (123,'A'),
(123,'B'),
(223,'B'),
(223,'C'),
(323,'C'),
(323,'D'),
(423,'E');
CREATE TABLE #data2
(
OrderId INT,
ProductId CHAR(1),
Grp INT
);
WITH cte AS
(
SELECT OrderId,
ProductId,
DENSE_RANK() OVER (ORDER BY ProductId) r
FROM #data
)
INSERT INTO #data2(OrderId, ProductId, Grp)
SELECT cte.OrderId,
cte.ProductId,
r
FROM cte
DECLARE @updates INT = 1;
WHILE @updates > 0
BEGIN
-- join groups where there is a lower numbered group that it connects to
UPDATE a
SET Grp = b.Grp
FROM #data2 a
INNER JOIN #data2 b ON b.OrderId = a.OrderId
OR b.ProductId = a.ProductId
WHERE a.Grp > b.Grp
-- end when we have done nothing this cycle
SET @updates = @@ROWCOUNT
END
SELECT
STUFF((SELECT DISTINCT '|'+ ProductId
FROM #data2
WHERE grp = o.grp
FOR xml path('')
), 1, 1, '') AS Products,
COUNT(DISTINCT o.OrderId) AS NumOrders
FROM #data2 o
GROUP BY grp