仅使用where条件删除重复项

时间:2017-02-14 12:00:28

标签: sql oracle

今天,我遇到了朋友的问题。

问题 - 使用UNION ALL(非union)编写SQL查询,该查询使用where子句来消除重复项。

  • 我不能使用group by expression
  • 我无法使用独特,独特的关键字。

输入 -

 id(Table 1)  
 1
 2

 fk_id(Table 2)
 1
 1
 2

我给了他查询以下的解决方案

select id from
(
select id , row_number() over(partition by id order by id) rn from
(
select id from T1
union all
select fk_ID id from T2
)
)where rn = 1;

Output - 
id
1
2

正在生成唯一ID。

现在他的悬念我也不能使用row_number()。我只需要使用条件。我在oracle数据库上写查询。

请建议。

提前致谢。

3 个答案:

答案 0 :(得分:4)

从其名称和显示的数据中,我们可以假设表id中的t1是唯一的。

从名称和显示的数据中,我们可以假设表fk_id中的t2table1.id的外键。

因此,两个表中ID的联合只是我们在表t1中找到的ID。

由于我们被迫在两个表上使用UNION ALL,我们可以使用伪UNION ALL来不添加任何内容:

select id from t1
union all
select fk_id from t2 where 1 = 2;

如果t2.fk_id不是引用t1.id的外键,我们会在where子句中使用NOT EXISTSNOT IN。但是,如果这是为了给出没有重复的结果,那么t2中必须没有重复项。 (当您显示t2中存在重复值时,此方法将不起作用。)以下是t1的唯一值加上t2的唯一值的查询引用t1值:

select id from t1
union all
select fk_id from t2 where fk_id not in (select id from t1);

答案 1 :(得分:2)

在一个更通用的情况下,你可以在两个表中都有重复项,这可能是一种方式。

测试数据:

create table table1(id) as (  
    select 1 from dual union all
    select 1 from dual union all
    select 2 from dual union all
    select 2 from dual union all
    select 1 from dual
)

create table table2(fk_id) as (
    select 1 from dual union all
    select 1 from dual union all
    select 1 from dual union all
    select 3 from dual union all
    select 4 from dual union all
    select 1 from dual union all
    select 4 from dual union all
    select 2 from dual 
)

<强>查询:

with tab1_union_all_tab2 as ( 
    select 'tab1'||rownum as uniqueId, id    from table1 UNION ALL
    select 'tab2'||rownum            , fk_id from table2
)    
select id
from tab1_union_all_tab2 u1
where not exists ( select 1
                   from tab1_union_all_tab2 u2
                   where u1.id = u2.id
                     and u1.uniqueId < u2.uniqueId
                 ) 

<强>结果:

    ID
----------
         3
         4
         1
         2

这应该澄清背后的想法:

with tab1_union_all_tab2 as ( 
    select 'tab1'||rownum as uniqueId, id    from table1 UNION ALL
    select 'tab2'||rownum            , fk_id from table2
)    
select uniqueId, id,
       ( select nvl(listagg ( uniqueId, ', ') within group ( order by uniqueId), 'NO DUPLICATES')
          from tab1_union_all_tab2 u2
         where u1.id = u2.id
           and u1.uniqueId < u2.uniqueId
       ) duplicates
from tab1_union_all_tab2 u1

UNIQUEID           ID DUPLICATES
---------- ---------- --------------------------------------------------
tab11               1 tab12, tab15, tab21, tab22, tab23, tab26
tab12               1 tab15, tab21, tab22, tab23, tab26
tab13               2 tab14, tab28
tab14               2 tab28
tab15               1 tab21, tab22, tab23, tab26
tab21               1 tab22, tab23, tab26
tab22               1 tab23, tab26
tab23               1 tab26
tab24               3 NO DUPLICATES
tab25               4 tab27
tab26               1 NO DUPLICATES
tab27               4 NO DUPLICATES
tab28               2 NO DUPLICATES

正如Thorsten Kettner正确观察到的那样,您可以轻松编辑此内容以使用rowid,而不是通过连接字符串和rownum来构建唯一ID:

with tab1_union_all_tab2 as ( 
    select rowid uniqueId, id    from table1 UNION ALL
    select rowid           , fk_id from table2
)    
select id
from tab1_union_all_tab2 u1
where not exists ( select 1
                   from tab1_union_all_tab2 u2
                   where u1.id = u2.id
                     and u1.uniqueId < u2.uniqueId
                 )

答案 2 :(得分:1)

为union中的第二个select写一个where语句,其中id为!!fk_id