为什么这个 WHERE NOT EXISTS() 条件返回 false pos/neg? (Itzik Ben-Gan 找出差距)

Why is this WHERE NOT EXISTS() condition returning false pos/neg? (Itzik Ben-Gan identifying gaps)

我正在学习 Ben Itzik-Gans 的 'solution 1' 方法来寻找差距以应用于业务问题。

代码在这里:http://rextester.com/CPXO58771

首先,您从序列值列表开始,其中一些会破坏序列:

| A.seqval |
|----------|
| 2        |
| 3        |
| 11       |
| 12       |
| 13       |
| 31       |
| 33       |
| 34       |
| 35       |
| 42       |

此查询产生以下结果:

SELECT
    seqval + 1 AS start_range
    ,(SELECT MIN(B.seqval) 
      FROM dbo.NumSeq AS B
      WHERE B.seqval > A.seqval) - 1 AS end_range
FROM 
    dbo.NumSeq AS A
WHERE 1=1
    AND NOT EXISTS (SELECT * 
                    FROM dbo.NumSeq AS B
                    WHERE B.seqval = A.seqval + 1)
    AND seqval < (SELECT MAX(seqval) FROM dbo.NumSeq)


| start_range | end_range |
|-------------|-----------|
| 4           | 10        |
| 14          | 30        |
| 32          | 32        |
| 36          | 41        |

我很难理解 WHERE NOT EXISTS() 过滤器是如何工作的。我逐行检查 NOT EXISTS() 子查询中的逻辑:

| A.seqval | A.seqval+1 |   | B.seqval |   | NOT EXISTS (SELECT * FROM NumSeq AS B WHERE B.seqval=A.seqval+1)        |
|----------|------------|---|----------|---|-------------------------------------------------------------------------|
| 2        | 3          |   | 2        |   | TRUE- there is no A.seqval+1 = 2                                        |
| 3        | 4          |   | 3        |   | FALSE- there is a A.seqval+1 row = 3                                    |
| 11       | 12         |   | 11       |   | TRUE- there is no A.seqval+1 = 11                                       |
| 12       | 13         |   | 12       |   | FALSE- there is a A.seqval+1 row = 12                                   |
| 13       | 14         |   | 13       |   | FALSE- there is a A.seqval+1 row = 13                                   |
| 31       | 32         |   | 31       |   | ??? -there is no A.seqval+1 = 31, but this returns as TRUE in the query |
| 33       | 34         |   | 33       |   | TRUE- there is no A.seqval+1 = 33                                       |
| 34       | 35         |   | 34       |   | FALSE- there is a A.seqval+1 row = 34                                   |
| 35       | 36         |   | 35       |   | FALSE- there is a A.seqval+1 row = 35                                   |
| 42       | 43         |   | 42       |   | TRUE- there is no A.seqval+1 = 42                                       |
  1. 如果 NOT EXISTS() 为值不存在的行返回 TRUE,是否不应该将它们包含在输出中而不是排除在输出中?
  2. 当 seqval=31 返回为 FALSE 时,如何将其识别为真阳性?

我不认为你在你的 stepthru 中处理不存在的 not

考虑第一条记录2+1 = 3。3存在于数据集中。所以不存在 3 = false 不正确。集合 {A} 和集合 {B} 在集合 A.SeqNum+1 = B.SeqNum

上进行比较
  A         B      Exists  Not Exists
            2      NEVER Needed as we always look A.SEQVAL+1
2+1 = 3     3      True    False
3+1 = 4     NULL   False   True
31+1 = 32   NULL   False   True
42          NULL   (never evaluated because of `where seqval < (SELECT MAX(seqval) FROM dbo.NumSeq)`

继续进行 31... 31+1 = 32.. 集合中不存在 32.. 正确。应该如此。

如果我们问集合中是否存在 32,那将是错误的。但由于它不存在....是的。

+----------+------------+-------------------------------------+----------------------------------+--------+------------+-----------------------------------------+
| A.SeqVal | A.SeqVal+1 | Does A.SeqVal+1 exist in A.SEQ Val? | Since it exists do we return it? | SeqVal | Now Add 1  | Now subtract 1 from next value in A.Seq |
+----------+------------+-------------------------------------+----------------------------------+--------+------------+-----------------------------------------+
|        2 |          3 | Yes                                 | No                               |        |            |                                         |
|        3 |          4 | No                                  | Yes                              |      3 | 4          |                                      10 |
|       11 |         12 | Yes                                 | No                               |        |            |                                         |
|       12 |         13 | Yes                                 | No                               |        |            |                                         |
|       13 |         14 | No                                  | Yes                              |     12 | 13         |                                      30 |
|       31 |         32 | No                                  | yes                              |     31 | 32         |                                      32 |
|       33 |         34 | Yes                                 | No                               |        |            |                                         |
|       34 |         35 | Yes                                 | No                               |        |            |                                         |
|       35 |         36 | No                                  | Yes                              |     35 | 36         |                                      41 |
|       42 |         43 | No                                  | Yes                              |     42 | Ignore max |                                         |
+----------+------------+-------------------------------------+----------------------------------+--------+------------+-----------------------------------------+
  • 现在添加一个(为什么?因为我们知道序列中的下一个值是缺失范围中的第一个值)
  • 现在从 a.Seqval 中的下一个值减一(为什么?因为我们知道该值存在;但它之前的值不存在)