SQL";选择不在子查询中的位置";不返回任何结果
免责声明:我已经解决了这个问题(我想),但我想把这个问题添加到堆栈溢出中,因为我(很容易)在任何地方都找不到它。另外,有人可能比我有更好的答案 我有一个数据库,其中一个表“Common”被其他几个表引用。我想看看公共表中哪些记录是孤立的(即,没有来自任何其他表的引用) 我运行了以下查询:SQL";选择不在子查询中的位置";不返回任何结果,sql,sql-server,tsql,Sql,Sql Server,Tsql,免责声明:我已经解决了这个问题(我想),但我想把这个问题添加到堆栈溢出中,因为我(很容易)在任何地方都找不到它。另外,有人可能比我有更好的答案 我有一个数据库,其中一个表“Common”被其他几个表引用。我想看看公共表中哪些记录是孤立的(即,没有来自任何其他表的引用) 我运行了以下查询: select * from Common where common_id not in (select common_id from Table1) and common_id not in (select c
select *
from Common
where common_id not in (select common_id from Table1)
and common_id not in (select common_id from Table2)
我知道有一些孤立的记录,但没有返回任何记录。为什么不呢
(这是SQL Server,如果有关系的话。)表1或表2的公用id有一些空值。请改用此查询:
select *
from Common
where common_id not in (select common_id from Table1 where common_id is not null)
and common_id not in (select common_id from Table2 where common_id is not null)
就在我的头顶上
select c.commonID, t1.commonID, t2.commonID
from Common c
left outer join Table1 t1 on t1.commonID = c.commonID
left outer join Table2 t2 on t2.commonID = c.commonID
where t1.commonID is null
and t2.commonID is null
我做了一些测试,下面是我的结果w.r.t.@patmortech的答案和@rexem的评论
如果Table1或Table2未在commonID上编制索引,则会得到一个表扫描,但@patmortech的查询速度仍然是100K行主表的两倍
如果两者都没有在commonID上建立索引,则会得到两次表扫描,差异可以忽略不计
如果两者都在commonID上建立索引,“not exists”查询将以1/3的时间运行。如果您希望世界是一个两值布尔位置,您必须自己防止null(第三个值)情况
SELECT T.common_id
FROM Common T
LEFT JOIN Table1 T1 ON T.common_id = T1.common_id
LEFT JOIN Table2 T2 ON T.common_id = T2.common_id
WHERE T1.common_id IS NULL
AND T2.common_id IS NULL
不要写入允许列表端为空的子句。过滤掉它们
common_id not in
(
select common_id from Table1
where common_id is not null
)
让我们假设公共_id的这些值:
Common - 1
Table1 - 2
Table2 - 3, null
我们希望公共行返回,因为它不存在于任何其他表中。但是,null会抛出一个活动扳手
使用这些值,查询相当于:
select *
from Common
where 1 not in (2)
and 1 not in (3, null)
select *
from Common
where not (1=2)
and not (1=3 or 1=null)
这相当于:
select *
from Common
where 1 not in (2)
and 1 not in (3, null)
select *
from Common
where not (1=2)
and not (1=3 or 1=null)
问题就从这里开始。与空值比较时。因此,查询简化为
select *
from Common
where not (false)
and not (false or unkown)
false或unknown是未知的:
select *
from Common
where true
and not (unknown)
真实而非未知也是未知的:
select *
from Common
where unknown
where条件不会返回结果未知的记录,因此我们不会返回任何记录
处理这个问题的一种方法是使用exists操作符,而不是in。Exists从不返回UNKNOWN,因为它对行而不是列进行操作。(行存在或不存在;行级别没有任何空歧义!)
更新: 我博客中的这些文章更详细地描述了两种方法之间的差异:
有三种方法可以执行此查询:
:左连接/为空
SELECT * FROM common LEFT JOIN table1 t1 ON t1.common_id = common.common_id WHERE t1.common_id IS NULL
:不存在
SELECT * FROM common WHERE NOT EXISTS ( SELECT NULL FROM table1 t1 WHERE t1.common_id = common.common_id )
:不在
SELECT * FROM common WHERE common_id NOT IN ( SELECT common_id FROM table1 t1 )
table1.common_id
不可为空时,所有这些查询在语义上都是相同的
当它可为空时,不在
是不同的,因为在
中(因此,不在
中)当值与包含空
的列表中的任何内容不匹配时,返回空
这可能会让人困惑,但如果我们回忆起这方面的替代语法,可能会变得更加明显:
common_id = ANY
(
SELECT common_id
FROM table1 t1
)
此条件的结果是列表中所有比较的布尔乘积。当然,一个NULL
值会产生NULL
结果,它也会呈现整个结果NULL
我们永远不能肯定地说,common\u id
不等于此列表中的任何值,因为至少有一个值是NULL
假设我们有这些数据:
common
--
1
3
table1
--
NULL
1
2
LEFT JOIN/IS NULL
和NOT EXISTS
将返回3
,NOT IN
将不返回任何内容(因为它将始终计算为FALSE
或NULL
)
在MySQL
中,如果在不可为NULL的列上,LEFT JOIN/IS NULL
和NOT In
比NOT EXISTS
的效率要高一点(百分之几)。如果列可为空,不存在
是最有效的(同样,也不是很多)
在Oracle
中,所有三个查询都会生成相同的计划(一个反连接
)
在SQL Server中,不在
/不存在
更有效,因为其优化器无法将左连接/为空
优化为反连接
在PostgreSQL
中,左连接/为空
和不存在
比不在
中更有效,因为它们被优化为反连接
,而不在
使用散列子计划
(如果子查询太大而无法散列,则使用普通的子计划
)这对我来说很有效:)
从“公用”中选择*
在哪里
公共id不在(从表1中选择ISNULL(公共id,'dummy-data'))
和公共id不在(从表2中选择ISNULL(公共id,'dummy-data'))
我举了一个例子,其中我正在查找,因为一个表中的值是双精度的,而另一个表中的值是字符串,所以它们不匹配(或者没有强制转换就不匹配)。但只有不在中。作为选择。。。在…中工作。奇怪,但我想我会与大家分享,以防其他人遇到这个简单的修复方法。请按照下面的示例理解上述内容 主题: 您也可以访问以下链接了解 但是如果我们在中使用
NOT,那么我们就不会得到任何数据
select Department_name,department_id from hr.departments dep
where department_id not in (select department_id from hr.employees );
没有找到任何数据
发生这种情况的原因是(从hr.employees中选择部门id
)返回空值,并且整个查询的计算结果为false。我们可以看到,如果我们稍微像下面这样更改SQL,并使用NVL函数处理空值
select Department_name,department_id from hr.departments dep
where department_id not in (select NVL(department_id,0) from hr.employees )
现在我们得到了数据:
DEPARTMENT_NAME DEPARTMENT_ID
Treasury 120
Corporate Tax 130
Control And Credit 140
Shareholder Services 150
Benefits 160
....
在使用NVL函数处理空值时,我们再次获得数据。如果一个表中有数据,而另一个表中没有数据,该怎么办?你想要“and”或“or”吗?我在寻找任何表中都没有引用的记录,所以我想要and。我会澄清这个问题。那应该是where子句中的AND。否则,这个世界
select Department_name,department_id from hr.departments dep
where department_id not in (select NVL(department_id,0) from hr.employees )
select Department_name,department_id from hr.departments dep
where department_id not in (select NVL(department_id,0) from hr.employees )
DEPARTMENT_NAME DEPARTMENT_ID
Treasury 120
Corporate Tax 130
Control And Credit 140
Shareholder Services 150
Benefits 160
....