今天,我遇到了朋友的问题。
问题 - 使用UNION ALL(非union)编写SQL查询,该查询使用where子句来消除重复项。
输入 -
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数据库上写查询。
请建议。
提前致谢。
答案 0 :(得分:4)
从其名称和显示的数据中,我们可以假设表id
中的t1
是唯一的。
从名称和显示的数据中,我们可以假设表fk_id
中的t2
是table1.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 EXISTS
或NOT 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