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
中查询(PROP1, PROP2)
元组中缺少的NUM值,例如(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。
答案 0 :(得分:1)
这会做你想要的,但我不知道它是否会更有效:
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
,然后进行最终比较。
答案 1 :(得分:1)
我就是这样做的
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一次,但我没有找到解决方案,如果其他人找到了解决方案,我会被强迫。
答案 2 :(得分:1)
根据Gordon对性能的回答,IS NULL
可能是性能问题。
IS NULL
会抑制index
的使用。因为NULL
值未编入索引。
有两种方法可以使用IS NULL
索引:
1。BITMAP
索引。但是,更适用于OLTP
系统。
2.我最喜欢的方式,很高兴展示。我们可以制作 leaves of the b-tree index a constant
。因此,在查询NULL
时使用索引。基本上,NULL都在索引的顶部/底部。 Oracle可以使用索引forwards or backwards
,因此并不重要。它会执行 full scan of the index
。
我在这里回答了类似的问题http://www.orafaq.com/forum/mv/msg/194746/625371/#msg_625371
由于OR为空条件,第一种情况不会使用索引:
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. Select all if parameter is null else return specific item issue