我有两个具有以下模式的表
id, fruit
在TableA中,值如下:
A01, Apple
A02, Orange
A03, Pineapple
A03, Pineapple
A05, Banana
在TableB中,值如下:
A01, Apple
A02, Orange
A03, Pineapple
A04, Pineapple
A05, Banana
如何协调这两个表以仅返回TableA中的重复行A03?就像一对一比较元组并返回奇数元组。
我尝试了如下的减号查询
Select * from TableA
minus
Select * from TableB
但这并没有返回我期望的结果集。
答案 0 :(得分:2)
好像您想从B中排除A中存在的行,而只排除确切的行。我猜你可以简单地给他们分配一个行号:
SELECT "id", "fruit", ROW_NUMBER() OVER (PARTITION BY "id", "fruit" ORDER BY NULL) AS rn
FROM TableA
MINUS
SELECT "id", "fruit", ROW_NUMBER() OVER (PARTITION BY "id", "fruit" ORDER BY NULL) AS rn
FROM TableB
答案 1 :(得分:1)
许多年前,Marco Stefanetti在AskTom上提出了以下出色的方法。它只要求每个表读取一次,并且只执行一种排序。
上下文是最通用的:查询将查找一个表中存在的行,而不是另一表中的行,但是-允许重复时-还将查找两个表中都存在的行,但行号不同重复项。
我在WITH子句中创建测试数据;在测试解决方案时,可以将其删除并从最后一条SELECT语句开始。
with
tablea (id, fruit) as (
select 'A01', 'Apple' from dual union all
select 'A02', 'Orange' from dual union all
select 'A03', 'Pineapple' from dual union all
select 'A03', 'Pineapple' from dual union all
select 'A05', 'Banana' from dual
)
, tableb (id, fruit) as (
select 'A01', 'Apple' from dual union all
select 'A02', 'Orange' from dual union all
select 'A03', 'Pineapple' from dual union all
select 'A04', 'Pineapple' from dual union all
select 'A05', 'Banana' from dual
)
select id, fruit, count(case source when 'tablea' then 1 end) as count_in_a,
count(case source when 'tableb' then 1 end) as count_in_b
from (
select id, fruit, 'tablea' as source from tablea
union all
select id, fruit, 'tableb' as source from tableb
)
group by id, fruit
having count(case source when 'tablea' then 1 end) !=
count(case source when 'tableb' then 1 end)
;
ID FRUIT COUNT_IN_A COUNT_IN_B
--- --------- ---------- ----------
A03 Pineapple 2 1
A04 Pineapple 0 1
答案 2 :(得分:-1)
这是您想要的吗?
Select id, fruit
from TableA
group by id, fruit
having count(*) > 1
minus
Select id, fruit
from TableB;
尚不清楚是否确实需要tableB
。如果您还需要其他列,则可以使用exists
来表示:
Select id, fruit
from (select a.*, count(*) over (partition by id, fruit) as cnt
from TableA a
) a
where cnt > 1 and
exists (select 1 from tableB b where b.id = a.id and b.fruit = a.fruit);
或使用in
:
Select id, fruit
from (select a.*, count(*) over (partition by id, fruit) as cnt
from TableA a
) a
where cnt > 1 and
(a.id, a.fruit) in (select b.id, b.fruit) from tableB);