在 SQL 中叠加行
Overlaying rows in SQL
因此,我想将键值对集合存储在数据库中,然后根据一系列集合检索组合的键值对集合。每组可能不完整。
假设我们有一个 table 如下:
create table MYTABLE (ROLE VARCHAR(62), KEY VARCHAR(62), VALUE VARCHAR(62));
insert into MYTABLE values('R1', 'K1', 'R1K1');
insert into MYTABLE values('R1', 'K2', 'R1K2');
insert into MYTABLE values('R1', 'K3', 'R1K3');
insert into MYTABLE values('R2', 'K1', 'R2K1');
insert into MYTABLE values('R2', 'K2', 'R2K2');
insert into MYTABLE values('R2', 'K4', 'R2K4');
insert into MYTABLE values('R3', 'K1', 'R3K1');
insert into MYTABLE values('R3', 'K4', 'R3K4');
insert into MYTABLE values('R3', 'K5', 'R3K5');
insert into MYTABLE values('R4', 'K1', 'R4K1');
insert into MYTABLE values('R5', 'K6', 'R5K6');
当给定序列 R1、R2、R3(或 R3、R2、R1,具体取决于您的观点)时,我想要以下结果:
+-----+-------+
| KEY | VALUE |
+-----+-------+
| K1 | R3K1 |
| K2 | R2K2 |
| K3 | R1K3 |
| K4 | R3K4 |
| K5 | R3K5 |
+-----+-------+
最初,我打算在 SQL 之外执行此操作,方法是检索每个集合并将结果转储到散列中,然后让后续项目覆盖之前的项目:
select KEY,VALUE from MYTABLE where ROLE = 'R1';
select KEY,VALUE from MYTABLE where ROLE = 'R2';
select KEY,VALUE from MYTABLE where ROLE = 'R3';
但如果可以混入很多角色,我不想为每个角色返回数据库。
最终我发现这些语句是可行的:
Oracle/DB2:
select distinct KEY, first_value(VALUE) over (partition by KEY order by decode(ROLE, 'R1', 1, 'R2', 2, 'R3', 3) desc) value from MYTABLE where ROLE in ('R1', 'R2', 'R3') order by KEY;
MySQL (guess):
select distinct KEY, first_value(VALUE) over (partition by KEY order by field(ROLE, 'R1, 'R2', 'R3') desc) value from MYTABLE where ROLE in ('R1', 'R2', 'R3') order by KEY;
(最后的“按 KEY 排序”对于我的需要来说并不是绝对必要的。)
有更好的方法吗?
您可以用 row_number()
表达该逻辑:
select key, value
from (
select t.*,
row_number() over(partition by key order by role) as rn
from mytable t
where role in ('R1', 'R2', 'R3')
) t
where rn = 1
这里并不真正需要条件排序,因为 'R1' < 'R2' < 'R3'
。但是如果你想对其他一些序列这样做,你通常会使用标准的 case
表达式:
select key, value
from (
select t.*,
row_number() over(
partition by key
order by case role when 'R1' then 1 when 'R2' then 2 when 'R3' then 3 end
) as rn
from mytable t
where role in ('R1', 'R2', 'R3')
) t
where rn = 1
这是一种相当可移植的语法,适用于许多数据库(只要它们支持 window 函数)。
因此,我想将键值对集合存储在数据库中,然后根据一系列集合检索组合的键值对集合。每组可能不完整。
假设我们有一个 table 如下:
create table MYTABLE (ROLE VARCHAR(62), KEY VARCHAR(62), VALUE VARCHAR(62));
insert into MYTABLE values('R1', 'K1', 'R1K1');
insert into MYTABLE values('R1', 'K2', 'R1K2');
insert into MYTABLE values('R1', 'K3', 'R1K3');
insert into MYTABLE values('R2', 'K1', 'R2K1');
insert into MYTABLE values('R2', 'K2', 'R2K2');
insert into MYTABLE values('R2', 'K4', 'R2K4');
insert into MYTABLE values('R3', 'K1', 'R3K1');
insert into MYTABLE values('R3', 'K4', 'R3K4');
insert into MYTABLE values('R3', 'K5', 'R3K5');
insert into MYTABLE values('R4', 'K1', 'R4K1');
insert into MYTABLE values('R5', 'K6', 'R5K6');
当给定序列 R1、R2、R3(或 R3、R2、R1,具体取决于您的观点)时,我想要以下结果:
+-----+-------+
| KEY | VALUE |
+-----+-------+
| K1 | R3K1 |
| K2 | R2K2 |
| K3 | R1K3 |
| K4 | R3K4 |
| K5 | R3K5 |
+-----+-------+
最初,我打算在 SQL 之外执行此操作,方法是检索每个集合并将结果转储到散列中,然后让后续项目覆盖之前的项目:
select KEY,VALUE from MYTABLE where ROLE = 'R1';
select KEY,VALUE from MYTABLE where ROLE = 'R2';
select KEY,VALUE from MYTABLE where ROLE = 'R3';
但如果可以混入很多角色,我不想为每个角色返回数据库。
最终我发现这些语句是可行的:
Oracle/DB2:
select distinct KEY, first_value(VALUE) over (partition by KEY order by decode(ROLE, 'R1', 1, 'R2', 2, 'R3', 3) desc) value from MYTABLE where ROLE in ('R1', 'R2', 'R3') order by KEY;
MySQL (guess):
select distinct KEY, first_value(VALUE) over (partition by KEY order by field(ROLE, 'R1, 'R2', 'R3') desc) value from MYTABLE where ROLE in ('R1', 'R2', 'R3') order by KEY;
(最后的“按 KEY 排序”对于我的需要来说并不是绝对必要的。)
有更好的方法吗?
您可以用 row_number()
表达该逻辑:
select key, value
from (
select t.*,
row_number() over(partition by key order by role) as rn
from mytable t
where role in ('R1', 'R2', 'R3')
) t
where rn = 1
这里并不真正需要条件排序,因为 'R1' < 'R2' < 'R3'
。但是如果你想对其他一些序列这样做,你通常会使用标准的 case
表达式:
select key, value
from (
select t.*,
row_number() over(
partition by key
order by case role when 'R1' then 1 when 'R2' then 2 when 'R3' then 3 end
) as rn
from mytable t
where role in ('R1', 'R2', 'R3')
) t
where rn = 1
这是一种相当可移植的语法,适用于许多数据库(只要它们支持 window 函数)。