English 中文(简体)
5. “选择不按子顺序”的回报没有结果
原标题:SQL "select where not in subquery" returns no results
  • 时间:2009-09-10 16:08:27
  •  标签:

Disapper: 我认为,我已经指出这一问题,但我想在Stack Overflow中增加这个问题,因为我(容易)在任何地方发现这个问题。 而且,一个人的答案可能比我更好的。

我有一个数据库,其中一个表格“Common”被其他几个表格参考。 我想看到共同表格中哪些记录是孤儿(即没有其他表格的提及)。

我要问:

select *
from Common
where common_id not in (select common_id from Table1)
and common_id not in (select common_id from Table2)

我知道有孤儿的记录,但没有归还记录。 为什么不呢?

(如果是的话,是服务器)。)

最佳回答

<>Update:

在我的博客中,这些条款更详细地描述了方法之间的差别:


有三个方法可以提出这样的问题:

  • LEFT JOIN / ISNUL:

    SELECT  *
    FROM    common
    LEFT JOIN
            table1 t1
    ON      t1.common_id = common.common_id
    WHERE   t1.common_id IS NULL
    
  • <编码> NOT EXISTS:

    SELECT  *
    FROM    common
    WHERE   NOT EXISTS
            (
            SELECT  NULL
            FROM    table1 t1
            WHERE   t1.common_id = common.common_id
            )
    
  • <编码> NOT IN:

    SELECT  *
    FROM    common
    WHERE   common_id NOT IN
            (
            SELECT  common_id
            FROM    table1 t1
            )
    

table1.common_id不可否认时,所有这些问题都是从属性的。

如无效,NOT IN则有所不同,因为IN(因此,NOT IN) 返回NUL,如果某一数值与载有< NUL的名单中的任何内容不一致的话。

这可能令人困惑,但如果我们回顾一下这方面的候补辛迪加的话,可能变得更加明显:

common_id = ANY
(
SELECT  common_id
FROM    table1 t1
)

这一状况的结果是清单内所有比较的 b。 当然,单一<代码>NUL 数值产生<代码>NUL,结果使整个结果成为NUL

我们永远不能说,<代码>common_id并不等于这一清单的任何内容,因为至少有一种价值是NUL

我们有这些数据:

common

--
1
3

table1

--
NULL
1
2

。 (因为总是对<代码>FALSE或>NUL进行评价。)

在<代码>MySQL中,对于无损栏目,LEFT JOIN / IS NUL的,其效率比低一些(单位:%) NOT EXISTS。 如果该栏不可行,NOT EXISTS则效率最高(而不是很大)。

在<代码>Oracle 中,所有三项查询都产生了相同的计划(ANTI JOIN)。

在<代码>SQL 服务器/代码>上,NOT IN/更有效率,因为LEFT JOIN / IS NUL不能优化为。 ANTI JOIN by its Bester.

PostgreSQL, LEFT JOIN / IS NULNOT EXISTS效率大于NOT IN,其ine被优化为Anti Join,而NOT IN >则使用hashed subplan (或甚至>,条件是该子座标价太大而已满。

问题回答

如果你想要世界成为两面价值大的宝石,那么你必须防止(第三面价值)的废墟。

不要在名单上写上允许作废的条款。 !!

common_id not in
(
  select common_id from Table1
  where common_id is not null
)

The short answer:

在贵邮局交还的藏书中,有一个民族解放军。 在完成分局之前或使用<代码>之前,你可以解决这个问题。 缩略语

The long answer (From T-SQL Fundamentals, Third edition, by Itzik Ben-Gan)

这方面的一个例子是:Imagine有一份订单,在销售内有一份UNL订单。 命令表,因此,分局将一些分类账和民族解放军的数值。

SELECT custid, companyname
FROM Sales.Customers
WHERE custid NOT IN(SELECT O.custid
             FROM Sales.Orders AS O);

解释上述询问为什么会归还一个空套:

Obviously, the culprit here is the NULL customer ID you added to the Orders table. The NULL is one of the elements returned by the subquery. Let’s start with the part that does behave like you expect it to. The IN predicate returns TRUE for a customer who placed orders (for example, customer 85), because such a customer is returned by the subquery. The NOT operator negates the IN predicate; hence, the NOT TRUE becomes FALSE, and the customer is discarded. The expected behavior here is that if a customer ID is known to appear in the Orders table, you know with certainty that you do not want to return it.

但是,如果客户的客户身份证明没有出现在订单中的非联合国利比里亚办事处客户身份证明中,并且还有一张<>UNL。 订单中的客户身份证明,你不能肯定地告诉客户有,同样,你也不能肯定地告诉客户没有客户。 没收? 我希望我能以一个实例澄清这一解释。

。 这是因为,如果你与已知客户身份比较,你就会获得FLSE,如果你与全国人民力量比较,你就会获得<代码>。 UNKNOWN。 。 考虑以下表述:22 NOT IN (1, 2, <other non-22 Value> NUL)。 这一表述可改写为。 您可将这一表述扩大到NOT (22 = 1 OR 22 = 2 OR OR 22 = NUL。 将括号中的每一个人表述评价到其真实价值上,并查阅<代码>。 注

The logical meaning of UNKNOWN here, before you apply the NOT operator, is that it can’t be determined whether the customer ID appears in the set, because the NULL could represent that customer ID. The tricky part here is that negating the UNKNOWN with the NOT operator still yields UNKNOWN. This means that in a case where it is unknown whether a customer ID appears in a set, it is also unknown whether it doesn’t appear in the set. Remember that a query filter discards rows that get UNKNOWN in the result of the predicate.

In short, when you use the NOT IN predicate against a subquery that returns at least one NULL, the query always returns an empty set. So, what practices can you follow to avoid such trouble? First, when a column is not supposed to allow NULLs, be sure to define it as NOT NULL. Second, in all queries you write, you should consider NULLs and the three-valued logic. Think explicitly about whether the query might process NULLs, and if so, whether SQL’s treatment of NULLs is correct for you. When it isn’t, you need to intervene. For example, our query returns an empty set because of the comparison with the NULL. If you want to check whether a customer ID appears only in the set of known values, you should exclude the NULLs—either explicitly or implicitly. To exclude them explicitly, add the predicate O.custid IS NOT NULL to the subquery, like this:

SELECT custid, companyname
FROM Sales.Customers
WHERE custid NOT IN(SELECT O.custid
                    FROM Sales.Orders AS O
                    WHERE O.custid IS NOT NULL);

You can also exclude the NULLs implicitly by using the NOT EXISTS predicate instead of NOT IN, like this:

SELECT custid, companyname
FROM Sales.Customers AS C
WHERE NOT EXISTS
   (SELECT *
    FROM Sales.Orders AS O
    WHERE O.custid = C.custid);

Recall that unlike IN, EXISTS uses two-valued predicate logic. EXISTS always returns TRUE or FALSE and never UNKNOWN. When the subquery stumbles into a NULL in O.custid, the expression evaluates to UNKNOWN and the row is filtered out. As far as the EXISTS predicate is concerned, the NULL cases are eliminated naturally, as though they weren’t there. So EXISTS ends up handling only known customer IDs. Therefore, it’s safer to use NOT EXISTS than NOT IN.

以上信息摘自第4章——分册、T-SQL Fundamentals,第三版<>。

表1或表2对共同价值有一些无效值。 而是利用这一询问:

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 *
from Common c
where not exists (select t1.commonid from table1 t1 where t1.commonid = c.commonid)
and not exists (select t2.commonid from table2 t2 where t2.commonid = c.commonid)

就在我头上台......

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

我进行了几次测试,这里是我的结果。

如果表1或表2没有按共同指数列出 ID,获得一张桌扫描,但@patmortech的盘点仍然比快两倍(100K浏览总桌)。

如果两者都没有在共同数据库中编入索引,那么就可得到两个表扫描仪,差额可以忽略不计。

如果两者都以共同数据库为索引,则“不存在”查询的时间为1/3。

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 - 1
Table1 - 2
Table2 - 3, null

我们希望共同的行会回来,因为在其他表格中都不存在。 然而,这名佛教徒扔在mon子里。

根据这些价值观,询问等于:

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)

这就是问题开始的原因。 http://itpov.com/archives/59“rel=“nofollow noreferer” 答案不明:。 因此,问题减少了。

select *
from Common
where not (false)
and not (false or unkown)

不详:

select *
from Common
where true
and not (unknown)

事实真相,并非无知:

select *
from Common
where unknown

情况没有恢复记录,结果没有确定,因此我们没有记录。

解决这一问题的办法之一是使用现有经营者,而不是使用。 极端主义者永远不会因为其是在行文而不是一栏活动而无知。 (一行要么存在,要么是 t;一行不明确!)

select *
from Common
where not exists (select common_id from Table1 where common_id = Common.common_id)
and not exists (select common_id from Table2 where common_id = Common.common_id)

这为我工作:

临时议程*

地点

共同点(见ISNUL(common_id, dummy-data ),表1)

表2显示的未在(选择ISNUL(common_id, dummy-data >)中

select *,
(select COUNT(ID)  from ProductMaster where ProductMaster.CatID = CategoryMaster.ID) as coun 
from CategoryMaster

我举了一个例子,因为一个表格的数值是两倍,而另一个表格则是一种扼杀,因此这些表格不匹配(或者不配上一片)。 但只有NOT IN。 http://www.ohchr.org。 更糟糕的是,我认为,如果任何其他人都遇到这种简单解决办法,我会分享。





相关问题