当基于两列不等式过滤时,SQL 中 WHERE 子句的幕后究竟发生了什么
What exactly is going on under the hood of WHERE clause in SQL when filtering based on two columns inequality
假设我们有以下 table:
简而言之,col1中有唯一的id,col2中有一些非唯一的对应值。
假设我们要查找 col2 值未唯一定义的行。
例如在以下示例中,此类行是 1 和 4。
col1
col2
1
"a"
2
"b"
3
"c"
4
"a"
所以我找到了以下看起来神秘的(对我来说)代码来完成这项工作(测试是上面 table 的名称):
SELECT *
FROM test a
WHERE col2 IN (SELECT col2 FROM test b WHERE b.col1 <> a.col1);
当然,完成任务的一种方法是按 col2 分组并过滤掉 count(col1) 等于 1 的那些值,但我关心的不是手头的任务,而是 WHERE 如何执行此上下文中的子句有效。
我知道 tables 是如何与 JOIN 显式连接的,我也了解像 WHERE somecol != value
这样的 WHERE 子句的常见用法。然而,WHERE somecol != othercol
在这种情况下的工作方式超出了我的范围。
有人可以告诉我上面的代码是如何工作的吗?
也许这个问题很愚蠢,如果是这样的话,对不起。
谢谢!
编辑:
Execution analysis here
在没有索引的情况下,这样的 where
子句通常将作为嵌套循环构造来实现。
也就是说,对于外部查询中的每一行,引擎将转到 运行 内部查询。对于每一行,它将比较 col1
。当它们不相等时,它将检查 col2
在外部查询中是否相同。
引擎确实有多种算法,因此不能保证这一点。但是,非平等条件更难优化且频率更低。
也就是说,有更有效的方式来表达查询。例如,您可以使用 window 函数。我相信这是相同的逻辑——假设列中的值不是 NULL
:
select t.*
from (select t.*,
min(col1) over (partition by col2) as min_col1,
max(col1) over (partition by col2) as max_col1
from test t
) t
where min_col1 <> max_col1;
假设我们有以下 table:
简而言之,col1中有唯一的id,col2中有一些非唯一的对应值。 假设我们要查找 col2 值未唯一定义的行。 例如在以下示例中,此类行是 1 和 4。
col1 | col2 |
---|---|
1 | "a" |
2 | "b" |
3 | "c" |
4 | "a" |
所以我找到了以下看起来神秘的(对我来说)代码来完成这项工作(测试是上面 table 的名称):
SELECT *
FROM test a
WHERE col2 IN (SELECT col2 FROM test b WHERE b.col1 <> a.col1);
当然,完成任务的一种方法是按 col2 分组并过滤掉 count(col1) 等于 1 的那些值,但我关心的不是手头的任务,而是 WHERE 如何执行此上下文中的子句有效。
我知道 tables 是如何与 JOIN 显式连接的,我也了解像 WHERE somecol != value
这样的 WHERE 子句的常见用法。然而,WHERE somecol != othercol
在这种情况下的工作方式超出了我的范围。
有人可以告诉我上面的代码是如何工作的吗? 也许这个问题很愚蠢,如果是这样的话,对不起。 谢谢!
编辑: Execution analysis here
在没有索引的情况下,这样的 where
子句通常将作为嵌套循环构造来实现。
也就是说,对于外部查询中的每一行,引擎将转到 运行 内部查询。对于每一行,它将比较 col1
。当它们不相等时,它将检查 col2
在外部查询中是否相同。
引擎确实有多种算法,因此不能保证这一点。但是,非平等条件更难优化且频率更低。
也就是说,有更有效的方式来表达查询。例如,您可以使用 window 函数。我相信这是相同的逻辑——假设列中的值不是 NULL
:
select t.*
from (select t.*,
min(col1) over (partition by col2) as min_col1,
max(col1) over (partition by col2) as max_col1
from test t
) t
where min_col1 <> max_col1;