sql - 如何将特定列值转换为 SQL 中一组值的标题?
问题描述
我有下表:
表A
+-----------+--------+--------------+
| tableA_id | code | Department |
+-----------+--------+--------------+
| 1 | code A | Science 1 |
| 2 | code B | Science 1 |
| 3 | code A | Science 2 |
| 4 | code C | Science 1 |
| 5 | code B | Science 2 |
| 6 | code A | Science 3 |
| 7 | code C | Science 2 |
| 8 | code B | Science 3 |
| 9 | code A | Science 4 |
| 10 | code C | Science 3 |
| 11 | code B | Science 4 |
+-----------+--------+--------------+
我想使用以下格式的 SQL 查询来转换它
+--------------+
| Department |
+--------------+
| Code A |
+--------------+
| Science 1 |
| Science 2 |
| Science 3 |
| Science 4 |
+--------------+
| Code B |
+--------------+
| Science 1 |
| Science 2 |
| Science 3 |
| Science 4 |
+--------------+
| Code C |
+--------------+
| Science 1 |
| Science 2 |
| Science 3 |
+--------------+
基本上我希望它按代码分组,但需要在每个组的顶部显示代码,并且列中的值不固定它是动态出现的。
解决方案
这可以通过group by rollup来实现。
初始解决方案
-- create sample data
declare @data table
(
id int,
code nvarchar(10),
department nvarchar(20)
);
insert into @data (id, code, department) values
( 1, 'code A', 'Science 1'),
( 2, 'code B', 'Science 1'),
( 3, 'code A', 'Science 2'),
( 4, 'code C', 'Science 1'),
( 5, 'code B', 'Science 2'),
( 6, 'code A', 'Science 3'),
( 7, 'code C', 'Science 2'),
( 8, 'code B', 'Science 3'),
( 9, 'code A', 'Science 4'),
(10, 'code C', 'Science 3'),
(11, 'code B', 'Science 4');
单个结果查询:
-- solution
select coalesce(d.department, d.code) as 'Department'
from @data d
group by d.code, d.department with rollup
having grouping(d.code) = 0
order by d.code, d.department;
运行此查询以了解我是如何得出上一个解决方案的:
-- solution explained
select grouping(d.department) as 'grouping_dep',
d.department,
grouping(d.code) as 'grouping_cod',
d.code,
coalesce(d.department, d.code) as 'Department',
case
when grouping(d.code) = 1 then 'aggregation across codes, filtered out with "having"'
else 'select "department", replace with "code" when null'
end as 'explanation'
from @data d
group by d.code, d.department with rollup -- group on every level and "roll up" the aggregations
order by d.code, d.department;
扩展解决方案
处理 2 个额外的列(基于评论中的额外输入)。
-- create sample data
declare @data table
(
id int,
code nvarchar(10),
department nvarchar(20),
colA nvarchar(10),
colB nvarchar(10)
);
insert into @data (id, code, department, colA, colB) values
( 1, 'code A', 'Science 1', 'A1_A', 'A1_B'),
( 2, 'code B', 'Science 1', 'B1_A', 'B1_B'),
( 3, 'code A', 'Science 2', 'A2_A', 'A2_B'),
( 4, 'code C', 'Science 1', 'C1_A', 'C1_B'),
( 5, 'code B', 'Science 2', 'B2_A', 'B2_B'),
( 6, 'code A', 'Science 3', 'A3_A', 'A3_B'),
( 7, 'code C', 'Science 2', 'C2_A', 'C2_B'),
( 8, 'code B', 'Science 3', 'B3_A', 'B3_B'),
( 9, 'code A', 'Science 4', 'A4_A', 'A4_B'),
(10, 'code C', 'Science 3', 'C3_A', 'C3_B'),
(11, 'code B', 'Science 4', 'B4_A', 'B4_B');
由于分组,您将需要使用聚合函数(如此处min
使用的函数)来选择值。
-- solution
select coalesce(d.department, d.code) as 'Department',
case when grouping(d.department)=1 then '' else min(d.colA) end as 'colA',
case when grouping(d.department)=1 then '' else min(d.colB) end as 'colB'
from @data d
group by d.code, d.department with rollup
having grouping(d.code) = 0
order by d.code, d.department;
这给出了:
Department colA colB
-------------------- ---------- ----------
code A
Science 1 A1_A A1_B
Science 2 A2_A A2_B
Science 3 A3_A A3_B
Science 4 A4_A A4_B
code B
Science 1 B1_A B1_B
Science 2 B2_A B2_B
Science 3 B3_A B3_B
Science 4 B4_A B4_B
code C
Science 1 C1_A C1_B
Science 2 C2_A C2_B
Science 3 C3_A C3_B
推荐阅读
- .net-core - 如何让 net-core 项目包含自动生成的代码文件?
- scope - 如何扩展 jq 'as' 变量的范围以在函数内部传递?
- php - php while循环在15行后不显示行
- javascript - 未处理的拒绝 (InvalidTokenError) 使用 async 和 await
- security - 如何为每月扫描的 30 个站点更好地管理 Qualys WAS
- java - 获取设备的位置,无论应用程序处于什么状态始终从我的公司应用程序中检测位置
- python - 混淆矩阵呈现一些空单元格
- regex - 如何在忽略第一场比赛的同时从一个点grep到另一个点?
- javascript - 如何从另一个组件更改组件状态?
- javascript - 这个参数化查询如何防止 SQL 注入?