【问题标题】:SQL Server Weird Grouping Scenario by multiple columns and ORSQL Server 奇怪的多列分组场景和 OR
【发布时间】:2019-01-08 23:08:08
【问题描述】:

我有一个奇怪的分组场景,并且在找出在 SQL 中分组的最佳方式时遇到了一些麻烦。

假设我们有以下一张表

CREATE TABLE Item
(
  KeyId VARCHAR(1) NOT NULL,
  Col1 INT NULL,
  Col2 INT NULL,
  Col3 INT NULL
)

GO

INSERT INTO Item (KeyId, Col1, Col2, Col3)
VALUES 
('a',1,2,3),
('b',5,4,3),
('c',5,7,6),
('d',8,7,9),
('e',11,10,9),
('f',11,12,13),
('g',20,22,21),
('h',23,22,24)

我需要对这张表中的记录进行分组,这样如果两条记录的 Col1 OR Col2 OR Col3 相同,那么这两条记录应该在同一个组中,并且应该有链接。 换句话说,对于上面的数据,记录'a'(第一条记录)的Col3 = 3,记录'b'(第二条记录)也有Col3 = 3,所以这两个应该在一个组中。但是记录'b'与记录'c'具有相同的Col1,因此记录'c'应该与'a'和'b'在同一组中。然后记录'd'与'c'具有相同的Col2,所以它也应该在同一个组中。同样,'e' 和 'f' 在 Col3 和 Col1 中分别具有相同的值。

另一方面,记录“g”和“h”将在一个组中(因为它们具有相同的 Col2 = 22),但该组将不同于记录“a”、“b”的组, 'c','d','e','f'。

查询的结果应该是这样的

KeyId GroupId
'a'   1 
'b'   1
'c'   1
'd'   1
'e'   1
'f'   1
'g'   2
'h'   2

可能有一种方法可以用一些循环/游标来做到这一点,但我开始考虑更清洁的方法,这似乎很困难。

【问题讨论】:

  • 我认为您需要在这里进行某种递归来构建集合。我认为没有一个常规查询可以一次性完成。
  • 也许你是对的,我想我可能遗漏了什么。
  • 我给了你一个赞成票,这是一个有趣的问题,但在我看来它需要动态编程,这很可怕。
  • 您需要使用递归 CTE。这个问题并不难。

标签: sql sql-server group-by


【解决方案1】:

给你:

with g (rootid, previd, level, keyid, col1, col2, col3) as (
  select keyid, '-', 1, keyid, col1, col2, col3 from item
  union all
  select g.rootid, g.keyid, g.level + 1, i.keyid, i.col1, i.col2, i.col3 
    from g
    join item i on i.col1 = g.col1 or i.col2 = g.col2 or i.col3 = g.col3 
    where i.keyid > g.keyid
),
  m (keyid, rootid) as (
  select keyid, min(rootid) from g group by keyid
)
select * from m;

结果:

keyid  rootid  
-----  ------
a      a       
b      a       
c      a       
d      a       
e      a       
f      a       
g      g       
h      g       

注意:请记住,SQL Server 在处理递归 CTE 时默认限制为 100 次迭代(每组的行数)。 英文:尽管可以如上所示执行此操作,但 SQL Server 可以处理的内容有明显的限制。如果达到此限制,您将收到以下消息:

在语句完成之前,最大递归 100 已经用完。

如果发生这种情况,请考虑添加子句option (maxrecursion 32767)

【讨论】:

  • 我们可以通过包含选项 (maxrecursion 0) 来覆盖 100 次迭代的默认限制;在 CTE 结束时
  • 是的,据我了解,SQL Server 中的最终最大值为 32767。
  • 我不确定我见过的迭代次数超过 1000 万次的最大限制
猜你喜欢
  • 1970-01-01
  • 2020-10-30
  • 2015-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-07
  • 2013-06-04
  • 2013-06-26
相关资源
最近更新 更多