我有一个包含当前值和默认值的表格。
GMT +05:30
任务是返回所有当前值并根据 ID 从默认值中添加缺失值。
我想知道最有效的方法是什么,我目前的方法是:
create table temp_se (
id varchar2(1),
default_value varchar2(1),
sequence number
)
/
insert into temp_se values ('A', 'N', 1);
insert into temp_se values ('B', 'N', 2);
insert into temp_se values ('C', 'N', 3);
insert into temp_se values ('D', 'N', 4);
insert into temp_se values ('E', 'N', null);
insert into temp_se values ('A', 'Y', null);
insert into temp_se values ('B', 'Y', null);
insert into temp_se values ('C', 'Y', null);
insert into temp_se values ('D', 'Y', null);
insert into temp_se values ('E', 'Y', 5);
/
我尝试了其他一些方法,包括下面的方法,但有些方法没有产生预期的结果,或者我不确定它是否在性能方面更好。也许有更好的方法来解决这个我不知道/没有尝试过的问题?
当前蚂蚁尝试的解决方案:
with data as
(select 1 rank, t.*
from temp_se t
where default_value = 'N'
and nvl(sequence, -1) < 3
union
select 2 rank, t.*
from temp_se t
where default_value = 'Y'),
ranked as
(select rank() over(partition by id order by rank) rank_no, t.* from data t)
select id, default_value, sequence from ranked where rank_no = 1;
/
--编辑--
预期结果:
ID | DEFAULT_VALUE | 序列 |
---|---|---|
A | N | 1 |
B | N | 2 |
C | 是 | |
D | 是 | |
E | N |
答案 0 :(得分:5)
重新表述您当前的方法
select id, default_value, sequence
from (
select t.* ,
row_number() over(partition by id order by case when default_value = 'N' then 1 else 2 end, nvl(sequence, -1) desc) rn
from temp_se t
where default_value = 'N' and (sequence is null or sequence < 3)
or default_value = 'Y'
) t
where rn = 1;
答案 1 :(得分:4)
您不需要工会或加入;您可以一次直接对行进行排名:
select id, default_value, sequence,
dense_rank() over (partition by id order by default_value, sequence) as rnk
from temp_se
where sequence is null or sequence < 3
然后将其用作 CTE 或线视图并过滤 rnk
:
select id, default_value, sequence
from (
select id, default_value, sequence,
dense_rank() over (partition by id order by default_value, sequence) as rnk
from temp_se
where sequence is null or sequence < 3
)
where rnk = 1
ID | DEFAULT_VALUE | 序列 |
---|---|---|
A | N | 1 |
B | N | 2 |
C | Y | null |
D | Y | null |
E | N | null |
答案 2 :(得分:3)
数据已经在一个表中,这似乎不是联合的情况,它似乎是过滤结果或条件聚合。
@Alex.poole 和 @serg 显示过滤,所以这里是聚合...
WITH
sample_data AS
(
-- Apply your filtering
SELECT t.*
FROM temp_se t
WHERE default_value = 'N' AND (sequence is null OR sequence < 3)
OR default_value = 'Y'
)
-- Aggregate to one row per id, prioritising default='N'
SELECT
id,
MIN(default_value) AS default_value,
MIN(sequence) KEEP (DENSE_RANK FIRST ORDER BY default_value) AS sequence
FROM
sample_data
GROUP BY
id
ORDER BY
id
这似乎是一个令人费解的场景。它只是一种将默认值存储在与源数据相同的表中的方法吗?为什么不单独存储默认值并使用 LEFT JOIN?