sql - 简短的 SQL Server 排名/分组脚本
问题描述
我有一个简单的客户表。
我需要为这些客户分配 groupID,但组中的最大记录数是@groupMaxVariable
.
GroupId 是按顺序分配的。如果没有客户有超过 5 条记录,那么客户组只会获得顺序 ID。
寻找简单的东西,而不是一些疯狂的嵌套游标。
create table #tempcust
(
id int,
name nvarchar(50),
amount nvarchar(50),
groupid int
)
insert into #tempcust (id,name,amount)
values
(1, 'Bob Smith', '$50.12'),
(2, 'Bob Smith', '$12.33' ),
(3, 'Bob Smith', '$33.12' ),
(4, 'Bob Smith', '$14.86' ),
(5, 'Bob Smith', '$6.36' ),
(6, 'Bob Smith', '$2.14'),
(7, 'Bob Smith', '$10.64'),
(8, 'Bob Smith', '$19.14'),
(9, 'Bob Smith', '$27.64'),
(10, 'Bob Smith', '$36.14'),
(11, 'Bob Smith', '$44.64'),
(12, 'Bob Smith', '$53.14'),
(13, 'Jane Doe', '$14.86' ),
(14, 'Jane Doe', '$6.36'),
(15, 'Jane Doe', '$2.14'),
(16, 'Jane Doe', '$10.64'),
(17, 'Jane Doe', '$19.14'),
(18, 'Jane Doe','$27.64'),
(19, 'Jane Doe', '$36.14'),
(20, 'Kylie Robinson', '$5.00') ,
(21, 'Kylie Robinson', '$6.00' ),
(22, 'Kylie Robinson', '$7.00' ),
(23, 'Kylie Robinson', '$8.00' ),
(24, 'Kylie Robinson', '$9.00' );
查询:
select
id, name, amount, groupid,
dense_rank() over (order by i.name) as Rank
from
#tempcust i
drop table #tempcust
结果:
id name amount groupid Rank
----------- -------------------------------------------------- -------------------------------------------------- ----------- --------------------
1 Bob Smith $50.12 NULL 1
2 Bob Smith $12.33 NULL 1
3 Bob Smith $33.12 NULL 1
4 Bob Smith $14.86 NULL 1
5 Bob Smith $6.36 NULL 1
6 Bob Smith $2.14 NULL 1
7 Bob Smith $10.64 NULL 1
8 Bob Smith $19.14 NULL 1
9 Bob Smith $27.64 NULL 1
10 Bob Smith $36.14 NULL 1
11 Bob Smith $44.64 NULL 1
12 Bob Smith $53.14 NULL 1
13 Jane Doe $14.86 NULL 2
14 Jane Doe $6.36 NULL 2
15 Jane Doe $2.14 NULL 2
16 Jane Doe $10.64 NULL 2
17 Jane Doe $19.14 NULL 2
18 Jane Doe $27.64 NULL 2
19 Jane Doe $36.14 NULL 2
20 Kylie Robinson $5.00 NULL 3
21 Kylie Robinson $6.00 NULL 3
22 Kylie Robinson $7.00 NULL 3
23 Kylie Robinson $8.00 NULL 3
24 Kylie Robinson $9.00 NULL 3
(24 row(s) affected)
预期结果
id Name Amount GroupID
1 Bob Smith $50.12 1
2 Bob Smith $12.33 1
3 Bob Smith $33.12 1
4 Bob Smith $14.86 1
5 Bob Smith $6.36 1
6 Bob Smith ($2.14) 2
7 Bob Smith ($10.64) 2
8 Bob Smith ($19.14) 2
9 Bob Smith ($27.64) 2
10 Bob Smith ($36.14) 2
11 Bob Smith ($44.64) 3
12 Bob Smith ($53.14) 3
13 Jane Doe $14.86 4
14 Jane Doe $6.36 4
15 Jane Doe ($2.14) 4
16 Jane Doe ($10.64) 4
17 Jane Doe ($19.14) 4
18 Jane Doe ($27.64) 5
19 Jane Doe ($36.14) 5
20 Kylie Robinson $5.00 6
21 Kylie Robinson $6.00 6
22 Kylie Robinson $7.00 6
23 Kylie Robinson $8.00 6
24 Kylie Robinson $9.00 6
解决方案
row_number()
在每个名称中,您可以使用和一些算术轻松枚举组。
然后,对于每个组,找到最小 id 并运行dense_rank()
在最小 id 上:
select c.*, dense_rank() over (order by min_grp_id) as groupid
from (select c.*, min(id) over (partition by name, within_name_groupId) as min_grp_id
from (select c.*,
lag(name) over (order by name) as prev_name,
(1 + (row_number() over (partition by name order by id) - 1) / 5
) as within_name_groupId
from tempcust c
) c
) c;
这是一个 db<>fiddle。
推荐阅读
- c# - 我怎样才能让我的跳跃和着陆动画可靠地播放?
- node.js - 尝试安装 Shopify Slate(Windows) 但它不起作用
- c - 函数中指针的值
- clips - 有没有办法定义 CLIPS 规则以搜索文本?
- python - 线性回归的实现,权重值增加到 Inf
- javascript - 如何在 React 中处理多个上下文?
- java - java servlet上下文无法加载application.property文件
- google-maps - 如何在 Flutter 中的 Google 地图上制作浮动搜索栏?
- sql - Spring Data JPA 不保留 oneToMany 列表
- html - nth-child 选择额外的元素