2015-09-15 11 views
5

Tôi muốn sử dụng FULL OUTER JOIN giữa hai bảng trên một số cột, nhưng khi cả hai cột đều rỗng, chúng không được coi là bằng nhau trong khi nối, vì vậy tôi có hai hàng khác nhau. Làm thế nào tôi có thể viết tham gia của tôi, do đó, các cột null được coi là bằng nhau?SQL: FULL OUTER JOIN trên các cột rỗng

tôi đã thiết lập một ví dụ đơn giản:

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); 

Kết quả thu được: enter image description here

Kết quả mong đợi: enter image description here

SQLFiddle

+0

Tại sao không chỉ tham gia vào các cột ID vì chúng là cả hai khóa chính cho các bảng tương ứng? – Sentinel

Trả lời

1

Sử dụng NVL() và một chuỗi duy nhất để thay thế 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') 
mã riêng

SQLFiddle demo

+1

Giải pháp này mất bất kỳ lợi ích nào của các chỉ mục trên trường1 và/hoặc field2 trừ khi các chỉ mục dựa trên chức năng được xác định – Sentinel

0

Các kết quả này không làm cho nó dễ dàng để phân biệt một NULL trong dữ liệu từ một NULL đại diện cho một thất bại để tham gia. Khi các giá trị null có mặt trong dữ liệu được nối, nó thường được ưu tiên bỏ qua chúng từ các kết quả bằng cách sử dụng một phép nối thông thường. Xem liên kết này: 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; 
0

Một giải pháp là sử dụng NVL và chuyển đổi NULL thành một giá trị vô hướng.

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) 
; 
+1

Tất cả các chỉ mục bị mất trừ khi các chỉ mục dựa trên chức năng phù hợp được tạo ra – Sentinel

+1

@Sentinel Vâng, đó là chính xác. –

0

Bên trong Oracle (cho làm mới cụ thể hóa quan điểm, chẳng hạn) làm cho việc sử dụng Sys_Op_Map_NonNull () cho chức năng này, điều này sẽ giúp bạn tham gia:

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)); 

Tôi không chắc chắn rằng việc sử dụng nó được hỗ trợ chính thức hoặc nếu họ đã bắt đầu ghi tài liệu công khai.

+0

giải pháp rất thú vị, cảm ơn bạn – bviale

2

NVL có thể được áp dụng trên các kết quả hiện không có chức năng là cần thiết trong điều kiện join

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)); 
+1

Đây là một giải pháp tốt. – Sentinel

+0

Tôi đã phải cập nhật truy vấn của mình ở những nơi có câu trả lời Husqvik (như được chọn cho câu trả lời mà VALEX cung cấp). Tôi nhận thấy tuy nhiên Sentinels bình luận về việc mất lợi thế lập chỉ mục. Tôi chỉ có 300 hàng. Nhưng nó là tốt để biết. Cảm ơn tất cả! – ionescu77

0

giải pháp này duy trì việc sử dụng các khoản sử dụng, nhưng loại bỏ một cột trong mệnh đề sử dụng có chứa null (field2). Thay vào đó field2 được kết hợp trong danh sách lựa chọn.

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. 
Các vấn đề liên quan