簡體   English   中英

SQL:空列上的FULL OUTER JOIN

[英]SQL : FULL OUTER JOIN on null columns

我想在幾個列的兩個表之間使用FULL OUTER JOIN ,但是當兩個列都為null時,它們在連接期間不被視為相等,因此我獲得兩個不同的行。 如何編寫連接,所以null列被認為是相等的?

我已經設置了一個簡化的例子:

create table t1 (
 id number(10) NOT NULL,
 field1 varchar2(50),
 field2 varchar2(50),
 CONSTRAINT t1_pk PRIMARY KEY (id)
);

create table t2 (
  id number(10) NOT NULL,
  field1 varchar2(50),
  field2 varchar2(50),
  extra_field number(1),
  CONSTRAINT t2_pk PRIMARY KEY (id)
);

insert into t1 values(1, 'test', 'test2');
insert into t2 values(1, 'test', 'test2', null);

insert into t1 values(2, 'test1', 'test1');
insert into t2 values(2, 'test1', 'test1', null);

insert into t1 values(3, 'test0', null);
insert into t2 values(3, 'test0', null, 1);

insert into t2 values(4, 'test4', 'test0', 1);

select *
from t1
full outer join t2 using (id, field1, field2);

獲得的結果: 在此輸入圖像描述

結果預期: 在此輸入圖像描述

SQLFiddle

使用NVL()和Unique String替換NULL:

select t1.id,t1.field1,t1.field2,t2.extra_field
from t1
full outer join t2 ON
t1.id=t2.id 
AND NVL(t1.field1,'UID_INSTEAD_OF_NULL')=NVL(t2.field1,'UID_INSTEAD_OF_NULL')
AND NVL(t1.field2,'UID_INSTEAD_OF_NULL')=NVL(t2.field2,'UID_INSTEAD_OF_NULL')

SQLFiddle演示

NVL可以應用於結果,因此在連接條件中不需要任何功能

select
    nvl(t1.id, t2.id) id,
    nvl(t1.field1, t2.field1) field1,
    nvl(t1.field2, t2.field2) field2,
    extra_field
from t1
full outer join t2 on t1.id = t2.id AND t1.field1 = t2.field1 AND (t1.field2 = t2.field2 OR (t1.field2 IS NULL AND t2.field2 IS NULL));

結果不容易區分數據中的NULL和表示連接失敗的NULL。 當要連接的數據中存在空值時,通常最好通過使用常規連接從結果中省略它們。 請看以下鏈接: https//technet.microsoft.com/en-us/library/ms190409(v = sql.105).aspx

select *
from t1, t2
where t1.id = t2.id and t1.field1 = t2.field1 and t1.field2 = t2.field2;

一種解決方案是使用NVL並將NULL轉換為標量值。

select *
from t1
full outer join t2 
  ON NVL(t1.id, 0) = NVL(t2.id, 0)
  AND NVL(t1.field1, 0) = NVL(t2.field1, 0)
  AND NVL(t1.field2, 0) = NVL(t2.field2, 0)
;

內部Oracle自己的代碼(例如,用於刷新物化視圖)使用Sys_Op_Map_NonNull()函數,這將使您的連接:

select *
from t1
full outer join t2 on (t1.id                         = t2.id and
                       t1.field1                     = t2.field2 and
                       Sys_Op_Map_NonNull(t1.field2) = Sys_Op_Map_NonNull(t2.field2));

我不確定它的使用是否得到官方支持,或者他們是否已經開始公開記錄它。

此解決方案維護using子句的使用,但消除了包含空值(field2)的using子句中的一列。 而是在選擇列表中合並field2。

select id
     , field1
     , coalesce(t1.field2,t2.field2) field2
     , extra_field
from t1
full outer join t2 using (id, field1); --field2 removed from using clause.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM