在 IN 条件下使用 Order By

Using Order By in IN condition

假设我们有这个愚蠢的查询:

Select * From Emp Where Id In (Select Id From Emp)

让我们通过添加 Order By 子句在 IN 条件内做一个小的修改。

Select * From Mail Where Id In (Select Id From Mail Order By Id)

然后我们收到以下错误:

ORA-00907: missing right parenthesis

Oracle 假定 IN 条件将在声明 From table 后结束。结果等待右括号,但我们给出了一个 Order By。 为什么我们不能在 IN 条件中添加一个 Order By?

仅供参考:我不要求等效查询。这毕竟是一个例子。我只是不明白为什么会出现这个错误。

考虑条件 x in (select something from somewhere)。如果 x 等于从查询返回的任何 something,它 returns 为真 - 无论它是第一个、第二个、最后一个还是中间的任何东西。 something 的返回顺序无关紧要。向查询添加 order by 子句通常会严重影响性能,所以我猜这个限制的引入是为了防止添加一个对查询的正确性没有影响的子句,一方面可能相当另一方面昂贵。

IN 子句中的值进行排序是没有意义的。这么想:

IN (a, b, c) 

相同
IN (c, b, a)

相同
IN (b, c, a)

Oracle 内部应用 OR 条件,因此它等同于:

WHERE id = a OR id = b OR id = c

订购这些条件有意义吗?

订购需自费。所以,当不需要排序的时候,干脆不做。在这种情况下,Oracle 应用了相同的规则。

当谈到查询的性能时,优化器需要选择最好的执行计划,即以最少的成本来实现所需的输出。 ORDER BY 在这种情况下是无用的,Oracle 很好地阻止了它的使用

对于documentation,

Type of Condition   Operation
-----------------   ----------
IN                  Equal-to-any-member-of test. Equivalent to =ANY.

因此,当您需要测试 ANY 值是否属于值列表中的成员时,不需要有序列表,只需随机匹配即可。

如果您查看 Oracle SQL 参考资料(语法图),您就会找到原因。 ORDER BY 是 "select" 语句的一部分,而 IN 子句使用情人级 "subquery" 语句。您的问题与 Oracle SQL 语法的性质有关。

PS:在 "subqueries" 上可能会有更多陷阱,例如多个 UNIONMINUS,然后您也只能使用一个 ORDER BY 子句,因为这仅适用于 UNION 操作的结果。 这也会失败:

select * from dual order by 1
union all
select * from dual order by 1;