簡體   English   中英

左連接並排除某些比賽中不存在的行

[英]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 constantleaves 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.

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