选择查询0 = 0 Vs不存在

时间:2018-11-12 10:22:01

标签: sql oracle

我有一个包含1亿行的表,我发现以下查询(A)耗时。我正在考虑将其更改为(B),是否一样?

此查询(A):

SELECT * 
FROM   tab1 
WHERE  code = 1 
       AND TYPE = 'A' 
       AND 0 = (SELECT Count(1) 
                FROM   tab1 
                WHERE  code = 1 
                       AND tr_type = 'APPROVE' 
                       AND security = 'Y')

类似于(B)吗?

SELECT * 
FROM   tab1 
WHERE  code = 1 
       AND TYPE = 'A' 
       AND NOT EXISTS (SELECT 1 
                       FROM   tab1 
                       WHERE  code = 1 
                              AND tr_type = 'APPROVE' 
                              AND security = 'Y' 
                              AND ROWNUM = 1)

4 个答案:

答案 0 :(得分:1)

是相同的查询。

SELECT * 
  FROM tab1 
 WHERE code = 1 
   AND type = 'A' 
   AND 0 = (SELECT Count(1) 
              FROM tab1 
             WHERE code = 1 
              AND  tr_type = 'APPROVE' 
              AND  security = 'Y') 

如果要在上述查询中获取内部查询的输出

SELECT Count(1) 
  FROM tab1 
 WHERE code = 1 
   AND tr_type = 'APPROVE' 
   AND security = 'Y'

我假设,存在code = 1TR_TYPE = 'APPROVE'security = 'Y'的记录。因此输出将为1。(假设只存在一个匹配的记录)。

SELECT * 
  FROM tab1 
 WHERE code =1 
   AND type='A' 
   AND 0=1 (replacing the result)

因此,由于0永远不等于1,因此不会返回任何数据。

SELECT * 
  FROM tab1 
 WHERE code = 1 
   AND type = 'A' 
   AND NOT EXISTS (SELECT 1 
                     FROM tab1 
                    WHERE code = 1 
                      AND tr_type = 'APPROVE' 
                      AND security = 'Y' 
                      AND rownum = 1)

现在检查上述查询,内部查询返回1,因为其中存在where子句的数据,所以结果为

SELECT * 
  FROM tab1 
 WHERE code =1 
   AND type='A' 
   AND NOT EXISTS (1)

Exists(If any record found) = true,在我们的情况下为Exists(1) = true,因此 Not Exist (1) = false。因为它有1条记录,所以它表示false,因此它也不会返回数据。

因此,如果您要求两个查询都将返回相同的输出。因此它将返回相同的输出。

答案 1 :(得分:1)

是的,输出将是相同的,因为它只是使用它的可互换方式,但是在时间复杂度方面,第二个输出已被优化。

答案 2 :(得分:1)

是的,它们是相同的,但是我会在不存在的表上显式地使用别名,并在要比较的列上使用别名。例如:

SELECT * 
  FROM tab1 
 WHERE code = 1 
   AND type = 'A' 
   AND NOT EXISTS (SELECT 1 
                     FROM tab1 b
                    WHERE b.code = 1 
                      AND b.tr_type = 'APPROVE' 
                      AND b.security = 'Y' 
                      AND rownum = 1)

答案 3 :(得分:1)

我建议将查询编写为:

SELECT t1.* 
FROM tab1 t1
WHERE t1.code = 1 AND
      t1.TYPE = 'A' AND
      NOT EXISTS (SELECT 1 
                  FROM tab1 tt1
                  WHERE tt1.code = t1.code AND 
                        tt1.tr_type = 'APPROVE' 
                        tt1.security = 'Y'
                 );

更改为:

  • 引入了表别名。
  • 所有列均合格。
  • rownum = 1条件已删除。

后者介于冗余和危险之间。 EXISTS / NOT EXISTS已经在寻找任何匹配的行。包含rownum 可以会影响优化程序。

您的第一个版本必须找到 all 个匹配项以计算计数。这比确定没有匹配项或找到第一个匹配项要昂贵得多。

为了提高性能,您希望在tab1(code, tr_type, security)tab1(code, type)上建立索引。