[英]Left join and excluding non-existent rows on certain matchups
TABLE1
PROP1 PROP2 NUM
a a 1
a a 2
a a 3
a b 1
a b 2
a b 3
TABLE2
PROP1 PROP2 NUM
a a 1
a a 2
我想查詢TABLE2
缺少的NUM值(PROP1, PROP2)
元組,如(a,b,3)
。 但是,如果TABLE2
中不存在元組,例如(a,b)
。 我不想在結果中返回它。
所以,我的預期輸出是
PROP1 PROP2 NUM
a a 3
在我寫的查詢之后,還返回(a,b)
元組,這是我不想要的。
SELECT *
FROM TABLE1 T1
LEFT JOIN TABLE2 T2 ON T1.PROP1 = T2.PROP1 AND T1.PROP2 = T2.PROP2 AND T1.NUM = T2.NUM
WHERE T2.NUM IS NULL
我想排除這3行,所以我再次與TABLE2
連接並將結果分組,這給了我正確的結果。
SELECT T1.PROP1, T1.PROP2, T1.NUM
FROM TABLE1 T1
LEFT JOIN TABLE2 T2 ON T1.PROP1 = T2.PROP1 AND T1.PROP2 = T2.PROP2 AND T1.NUM = T2.NUM
JOIN TABLE2 T22 ON T1.PROP1 = T22.PROP1 AND T1.PROP2 = T22.PROP2
WHERE T2.NUM IS NULL
GROUP BY T1.PROP1, T1.PROP2, T1.NUM
問題 :如果沒有GROUP BY
語句,我有什么方法可以做到這一點,因為它對於大型表來說有點窮舉。
我正在使用Oracle 11g。
這將做你想要的,但我不知道它是否會更有效:
SELECT *
FROM TABLE1 T1 JOIN
(SELECT DISTINCT PROP1, PROP2
FROM TABLE2
) TT2
ON T1.PROP1 = TT2.PROP1 AND t1.PROP2 = TT2.PROP2 LEFT JOIN
TABLE2 T2
ON T1.PROP1 = T2.PROP1 AND T1.PROP2 = T2.PROP2 AND T1.NUM = T2.NUM
WHERE T2.NUM IS NULL;
它首先在匹配的行上過濾table1
,然后進行最終比較。
我就是這樣做的
with table1 as
(select 'a' prop1, 'a' prop2, 1 num from dual
union all
select 'a' , 'a' , 2 from dual
union all
select 'a' , 'a' , 3 from dual
union all
select 'a' , 'b' , 1 from dual
union all
select 'a' , 'b' , 2 from dual
union all
select 'a' , 'b' , 3 from dual),
table2 as(
select 'a' prop1, 'a' prop2, 1 num from dual
union all
select 'a' , 'a' , 2 from dual
)
select prop1, prop2, num
from table1
where (prop1, prop2) in (select prop1, prop2 from table2)
minus
select prop1, prop2, num
from table2
另一種方法是:
select prop1, prop2, num
from table1
where (prop1, prop2, num) not in(select prop1, prop2, num
from table2)
and (prop1, prop2) in (select prop1, prop2 from table2)
編輯:我嘗試使用exists
來獲取它,只使用table2一次,但是我沒有找到解決方案,如果其他人找到了解決方案,我會被強迫。
根據Gordon關於性能的回答, IS NULL
可能是性能問題。
IS NULL
禁止index
使用。 因為NULL
值未編入索引。
有兩種方法可以使用帶有IS NULL
的索引:
1. BITMAP
指數。 但是,更適用於OLTP
系統。
我最喜歡的方式,很好地展示。 我們可以使leaves of the b-tree index a constant
的leaves of the b-tree index a constant
。 因此,在查詢NULL
使用索引。 基本上,NULL都在索引的頂部/底部。 Oracle可以使用索引forwards or backwards
,因此並不重要。 它會對full scan of the index
進行full scan of the index
。
我在這里回答了類似的問題http://www.orafaq.com/forum/mv/msg/194746/625371/#msg_625371
由於OR為null條件,第一種情況不會使用索引:
SQL> SELECT * FROM PROD_NEW; PROFILE_TYPE --------------- Prod Prodparallel Prod SQL> CREATE INDEX PROD_NEW_I1 ON PROD_NEW 2 (PROFILE_TYPE 3 ); Index created. SQL> EXPLAIN PLAN FOR SELECT * FROM PROD_NEW WHERE PROFILE_TYPE = 'Prod' OR PROFILE_TYPE IS NULL; Explained. SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY); PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- Plan hash value: 2121244107 ------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 3 | 15 | 3 (0)| 00:00:01 | |* 1 | TABLE ACCESS FULL| PROD_NEW | 3 | 15 | 3 (0)| 00:00:01 | ------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- 1 - filter("PROFILE_TYPE" IS NULL OR "PROFILE_TYPE"='Prod') 13 rows selected
讓葉子保持不變:
SQL> DROP INDEX PROD_NEW_I1; Index dropped. SQL> CREATE INDEX PROD_NEW_I1 ON PROD_NEW 2 (PROFILE_TYPE,1 3 ); Index created. SQL> EXPLAIN PLAN FOR SELECT * FROM PROD_NEW WHERE PROFILE_TYPE = 'Prod' OR PROFILE_TYPE IS NULL; Explained. SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY); PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- Plan hash value: 1272076902 -------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 3 | 15 | 1 (0)| 00:00:01 | |* 1 | INDEX FULL SCAN | PROD_NEW_I1 | 3 | 15 | 1 (0)| 00:00:01 | -------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- 1 - filter("PROFILE_TYPE" IS NULL OR "PROFILE_TYPE"='Prod') 13 rows selected. SQL>
我在這里回答了類似的問題, Oracle。 選擇all if參數為null,否則返回特定項目問題
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.