为什么这个 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 |
- 如果 NOT EXISTS() 为值不存在的行返回 TRUE,是否不应该将它们包含在输出中而不是排除在输出中?
- 当 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 中的下一个值减一(为什么?因为我们知道该值存在;但它之前的值不存在)
我正在学习 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 |
- 如果 NOT EXISTS() 为值不存在的行返回 TRUE,是否不应该将它们包含在输出中而不是排除在输出中?
- 当 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 中的下一个值减一(为什么?因为我们知道该值存在;但它之前的值不存在)