如何对按顺序排列的相同值进行分组
How to group the same values which is in sequence order
我正在尝试按顺序对数据进行分组。我有以下 table:
id num
-------
1 1
2 1
3 1
4 2
5 1
6 2
7 2
8 4
9 4
10 4
我需要 SQL 查询输出以下内容:
num count(num)
-------------------
1 3
2 1
1 1
2 2
4 3
示例数据:
select * into #temp
from (
select 1 as id, 1 as num union all
select 2, 1 union all
select 3, 1 union all
select 4, 2 union all
select 5, 1 union all
select 6, 2 union all
select 7, 2 union all
select 8, 4 union all
select 9, 4 union all
select 10, 4
) as abc
select * from #temp
select 数,计数(数)
来自#temp
按人数分组
我需要这个:
num count(num)
-------------------
1 3
2 1
1 1
2 2
4 3
实际输出:
num count(num)
---------------------
1 4
2 3
4 3
这是一个缺口和孤岛问题。这是使用 lag()
和累积 sum()
:
解决问题的一种方法
select
min(num) num,
count(*) count_num
from (
select
t.*,
sum(case when num = lag_num then 0 else 1 end) over(order by id) grp
from (
select
t.*,
lag(num) over(order by id) lag_num
from #temp t
) t
) t
group by grp
num | count_num
--: | --------:
1 | 3
2 | 1
1 | 1
2 | 2
3 | 3
另一种方法可以使用 row_number
select num, count(*)
from (select t.*,
(row_number() over (order by id) -
row_number() over (partition by num order by id)
) as grp
from #temp t
) t
group by grp, num;
差距和孤岛问题很有趣,因为有很多不同的方法可以解决它们。这是一种不需要聚合的方法——尽管它确实需要更多地使用 window 函数。
这是可能的,因为您请求的唯一信息是计数。如果 id
没有间隙并且是连续的:
select num,
lead(id, 1, max_id + 1) over (order by id) - id
from (select t.*,
lag(num) over (order by id) as prev_num,
max(id) over () as max_id
from temp t
) t
where prev_num is null or prev_num <> num
order by id;
否则,你可以轻松生成这样的序列:
select num,
lead(seqnum, 1, cnt + 1) over (order by id) - seqnum
from (select t.*,
lag(num) over (order by id) as prev_num,
row_number() over (order by id) as seqnum,
count(*) over () as cnt
from temp t
) t
where prev_num is null or prev_num <> num
order by id;
Here 是一个 db<>fiddle.
我正在尝试按顺序对数据进行分组。我有以下 table:
id num
-------
1 1
2 1
3 1
4 2
5 1
6 2
7 2
8 4
9 4
10 4
我需要 SQL 查询输出以下内容:
num count(num)
-------------------
1 3
2 1
1 1
2 2
4 3
示例数据:
select * into #temp
from (
select 1 as id, 1 as num union all
select 2, 1 union all
select 3, 1 union all
select 4, 2 union all
select 5, 1 union all
select 6, 2 union all
select 7, 2 union all
select 8, 4 union all
select 9, 4 union all
select 10, 4
) as abc
select * from #temp
select 数,计数(数) 来自#temp 按人数分组
我需要这个:
num count(num)
-------------------
1 3
2 1
1 1
2 2
4 3
实际输出:
num count(num)
---------------------
1 4
2 3
4 3
这是一个缺口和孤岛问题。这是使用 lag()
和累积 sum()
:
select
min(num) num,
count(*) count_num
from (
select
t.*,
sum(case when num = lag_num then 0 else 1 end) over(order by id) grp
from (
select
t.*,
lag(num) over(order by id) lag_num
from #temp t
) t
) t
group by grp
num | count_num --: | --------: 1 | 3 2 | 1 1 | 1 2 | 2 3 | 3
另一种方法可以使用 row_number
select num, count(*)
from (select t.*,
(row_number() over (order by id) -
row_number() over (partition by num order by id)
) as grp
from #temp t
) t
group by grp, num;
差距和孤岛问题很有趣,因为有很多不同的方法可以解决它们。这是一种不需要聚合的方法——尽管它确实需要更多地使用 window 函数。
这是可能的,因为您请求的唯一信息是计数。如果 id
没有间隙并且是连续的:
select num,
lead(id, 1, max_id + 1) over (order by id) - id
from (select t.*,
lag(num) over (order by id) as prev_num,
max(id) over () as max_id
from temp t
) t
where prev_num is null or prev_num <> num
order by id;
否则,你可以轻松生成这样的序列:
select num,
lead(seqnum, 1, cnt + 1) over (order by id) - seqnum
from (select t.*,
lag(num) over (order by id) as prev_num,
row_number() over (order by id) as seqnum,
count(*) over () as cnt
from temp t
) t
where prev_num is null or prev_num <> num
order by id;
Here 是一个 db<>fiddle.