合并两个结果集同时从一组结果中排除相同结果的最有效方法

时间:2021-06-21 14:32:48

标签: sql oracle

我有一个包含当前值和默认值的表格。

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

3 个答案:

答案 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

db<>fiddle

答案 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?

相关问题