SQL查询将连续范围的数字分组到不同的分组集中
Posted
技术标签:
【中文标题】SQL查询将连续范围的数字分组到不同的分组集中【英文标题】:SQL Query to group continuous range of numbers into different grouping sets 【发布时间】:2013-01-22 12:43:10 【问题描述】:我有一张包含大约一百万条记录的表。下面给出了几个示例值:
Group MemberNo
ABC 100
ABC 101
ABC 200
ABC 201
ABC 202
ABC 203
XYZ 100
XYZ 101
ABC 204
XYZ 301
XYZ 302
ABC 500
ABC 600
我希望将具有相同组的连续值范围分组为这样的集合:
Group FromMemberNo ToMemberNo
ABC 100 101
ABC 200 204
XYZ 100 101
XYZ 301 302
ABC 500 500
ABC 600 600
请从上表中看到,由于 100 和 101 是连续的,因此它已被分组为一条记录 ABC 100 到 101。我已经尝试过 this 线程并且对我来说工作正常。但这比预期花费的时间要长。 请帮助我实现这一目标。
提前致谢。
【问题讨论】:
在您链接的问题中接受的答案可能是最有效的方法。需要多长时间?您预计需要多长时间?执行计划是什么样的?你有Group,MemberNo
的索引吗?
嗨@MartinSmith,还有4 列,为简单起见,我只添加了1 列。我对所有这些列都有索引,但查询仍然需要 4 到 5 秒。
您每次都需要处理百万行吗?
嗨@HamletHakobyan,我打算在不触及我的应用程序逻辑的情况下将其作为数据层中的视图来实现。您是真的,不需要每次都处理所有行。
请发布您的实际表结构以及索引、您正在运行的查询和执行计划,我们可以查看您是否缺少任何可以避免排序的索引。
【参考方案1】:
另一种解决方案。我可以了解性能,但似乎可以完成工作(仅限 sql 2012)
declare @t table (g varchar(3), mn int)
insert into @t values
('ABC', 100),
('ABC', 101),
('ABC', 200),
('ABC', 201),
('ABC', 202),
('ABC', 203),
('XYZ', 100),
('XYZ', 101),
('ABC', 204),
('XYZ', 301),
('XYZ', 302),
('ABC', 500),
('ABC', 600),
('XYZ', 400);
with ctet as (
select
row_number() over (order by g, mn) rn,
*,
case when lag(mn, 1) over (order by g, mn) <> mn - 1 then 1 else 0 end as d
from
@t
)
select g, min(mn), max(mn)
from
(
select
*,
(select sum(d) from ctet vv where vv.rn <= ctet.rn) s
from
ctet
) v
group by g, s
我很确定存在滞后或领先的更智能解决方案,但我找不到。
===== 编辑 =====
终于也适用于 2005 年
with ctet as (
select
row_number() over (order by t.g, t.mn) rn,
t.*,
case when tt.g is null then 1 else 0 end as d
from
@t t
left join @t tt on t.g = tt.g and t.mn = tt.mn + 1
)
【讨论】:
谢谢,但@Andriy M 的解决方案只需要一点时间!以上是关于SQL查询将连续范围的数字分组到不同的分组集中的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server - 在按特定列分组时构建动态范围的数字