Sql 左连接并排除某些匹配上不存在的行
我想查询表2中缺少的关于PROP1、PROP2元组(如a、b、3)的NUM值。但是,如果表2中不存在元组,例如a、b。我不想在结果中返回它 因此,我的预期输出是Sql 左连接并排除某些匹配上不存在的行,sql,oracle,join,Sql,Oracle,Join,我想查询表2中缺少的关于PROP1、PROP2元组(如a、b、3)的NUM值。但是,如果表2中不存在元组,例如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 =
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行,所以我再次加入表2并对结果进行分组,从而得到正确的结果
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
问:有没有什么方法可以不用GROUPBY语句来完成,因为它对于大型表来说有点详尽
我正在使用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来获得它,只使用了一次表2,但我没有找到解决方案,如果其他人找到解决方案,我会感兴趣。根据Gordon关于性能的回答,IS NULL可能是性能问题
为NULL将禁止使用索引。因为空值没有索引
有两种方法可以使用带为NULL的索引:
1.位图索引。但是,更适用于OLTP系统
2.我最喜欢的方式,很好演示。我们可以使b-树索引的叶子保持不变。因此,在查询NULL时使用索引。基本上,空值都在一起,位于索引的顶部/底部。Oracle可以向前或向后使用索引,所以这并不重要。它会对索引进行完整扫描
我在这里回答了一个类似的问题
由于OR为null条件,第一个场景将不使用索引:
让我们使树叶保持不变:
我在这里回答了一个类似的问题,谢谢,T中有一个输入错误!顺便说一句,在我看来,整个左连接方法是个坏主意。如果左连接不存在,为什么要使用左连接来提问?
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)
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>