Oracle SQL - 组合两个表,但从一个表中获取重复项?

时间:2012-06-15 23:28:51

标签: sql oracle union

我有这些表格:

Table A
Num Letter 
1   A      
2   B      
3   C     

Table B
Num Letter
2   C      
3   D   
4   E 

我想结合这两个表,但我只希望每个数字出现一次。如果两个表中都出现相同的数字,我希望它来自表B而不是表A.

Result
Num Letter
1   A
2   C
3   D
4   E

我怎么能做到这一点?联合将保留重复,并且交叉将仅捕获相同的行 - 当具有相同的数字时,我认为该行是重复的,无论该字母是什么。

6 个答案:

答案 0 :(得分:1)

试试这个:http://www.sqlfiddle.com/#!4/0b796/1

with a as
(
  select Num, 'A' as src, Letter
  from tblA
  union
  select Num, 'B' as src, Letter
  from tblB
)
select 

   Num

   ,case when count(*) > 1 then
       min(case when src = 'B' then Letter end)
   else
       min(Letter)
   end as Letter

from a
group by Num
order by Num;

输出:

| NUM | LETTER |
----------------
|   1 |      A |
|   2 |      C |
|   3 |      D |
|   4 |      E |

答案 1 :(得分:1)

还有一个:

SELECT COALESCE(b.num, a.num) num, COALESCE(b.letter, a.letter) letter
  FROM a FULL JOIN b ON a.num = b.num
 ORDER BY 1;

使用您的数据:

WITH a AS 
(SELECT 1 num, 'A' letter FROM dual
 UNION ALL SELECT 2, 'B' FROM dual
 UNION ALL SELECT 3, 'C' FROM dual),
b AS
(SELECT 2 num, 'C' letter FROM dual
 UNION ALL SELECT 3, 'D' FROM dual
 UNION ALL SELECT 4, 'E' FROM dual)
SELECT COALESCE(b.num, a.num) num, COALESCE(b.letter, a.letter) letter
  FROM a FULL JOIN b ON a.num = b.num
 ORDER BY 1;

       NUM L
---------- -
         1 A
         2 C
         3 D
         4 E

答案 2 :(得分:0)

可能缺乏效率,但它会产生正确的答案。

select nums.num, coalesce(b.letter, a.letter)
from
(select num from b
union
select num from a) nums
left outer join b
on (b.num = nums.num)
left outer join a
on (a.num = nums.num);

答案 3 :(得分:0)

或者您可以使用特定于Oracle的技术来缩短代码:http://www.sqlfiddle.com/#!4/0b796/11

with a as
(
  select Num, 'A' as src, Letter
  from tblA
  union
  select Num, 'B' as src, Letter
  from tblB
)
select Num, min(Letter) keep(dense_rank first order by src desc) as Letter
from a
group by Num
order by Num;

输出:

| NUM | LETTER |
----------------
|   1 |      A |
|   2 |      C |
|   3 |      D |
|   4 |      E |

代码无论min(letter)还是max(letter)都有效,它具有相同的输出,它提供相同的输出。重要的是你使用keep dense_rank。另一个重要的事情是,订单很重要,我们使用order by src desc在保留一行时优先考虑源表B.


要真正缩短内容,请使用keep dense_rank last,并按顺序省略descasc无论如何都是默认http://www.sqlfiddle.com/#!4/0b796/12

with a as
(
  select Num, 'A' as src, Letter
  from tblA
  union
  select Num, 'B' as src, Letter
  from tblB
)
select Num, min(Letter) keep(dense_rank last order by src) as Letter
from a
group by Num
order by Num;

再一次,在Letter上使用minmax并不重要,只要你保持dense_rank获得优先级/首选行

答案 4 :(得分:0)

另一种选择是将UNION和MINUS命令组合如下:

SELECT 
    NUM, LETTER
FROM 
    TABLE B 
UNION 
( SELECT 
      NUM, LETTER 
  FROM 
      TABLE A 
  WHERE 
      NUM IN (SELECT
                  NUM
              FROM 
                  TABLE A 
              MINUS 
              SELECT 
                  NUM
              FROM 
                  TABLE B ))

答案 5 :(得分:0)

SELECT A.*
FROM A
WHERE A.NUM NOT IN
  (SELECT A.NUM
  FROM B
  WHERE A.NUM=B.NUM
  AND B.NUM IS NOT NULL
  AND A.NUM IS NOT NULL
  )
UNION
SELECT * FROM B;