1

我有这些表:

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

我怎么能做到这一点?联合将保留重复项,而相交只会捕获相同的行——无论字母如何,当它具有相同的数字时,我认为行是重复的。

4

6 回答 6

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 |
于 2012-06-15T23:54:09.283 回答
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
于 2012-06-16T00:46:49.123 回答
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 ))
于 2012-06-16T00:33:48.963 回答
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;
于 2012-06-16T07:20:29.640 回答
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);
于 2012-06-15T23:41:42.743 回答
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)or max(letter),代码都可以工作,它具有相同的输出,它给出相同的输出。重要的是您使用keep dense_rank. 另一个重要的事情是,顺序问题,我们order by src desc在保持一行时会优先考虑源表B。


为了真正让它更短,使用keep dense_rank last并省略descon order by,asc无论如何都是默认的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 上使用minormax并不重要,只要您保持 dense_rank 获得优先/首选行

于 2012-06-16T00:27:22.683 回答