这个 Oracle SQL SELECT 不应该工作。为什么呢?

This Oracle SQL SELECT shouldn't work. Why does it?

我正在调试 Oracle 19c 中的查询,该查询试图按不在查询中的字段对 SELECT DISTINCT 结果进行排序。 (注意:这是错误的做法,不要这样做。

此查询试图 return 一个唯一的客户名称列表,其中最近的销售日期排在最前面。它 return 是一个预期的错误,“ORA-01791:不是 SELECTed 表达式”。

SELECT DISTINCT CUSTOMER_NAME
FROM SALES
ORDER BY LAST_SALE_DATE DESCENDING;

它 return 是一个错误,因为查询试图按尚未 select 编辑的字段对结果进行排序。到目前为止这是有道理的。

但是,如果我只是将 FETCH FIRST 6 ROWS ONLY 添加到查询中,它会 而不是 return 错误(尽管结果不正确,所以不要做这个)。但问题是为什么Oracle没有return错误信息?

SELECT DISTINCT CUSTOMER_NAME
FROM SALES
ORDER BY LAST_SALE_DATE DESCENDING
FETCH FIRST 6 ROWS ONLY;

为什么添加 FETCH FIRST 6 ROWS ONLY 可以实现此功能?

补充:如果有多个记录具有相同的名称和日期,则不正确的查询将 return 重复。搜索类似“sql select distinct order by another column”之类的内容将显示几种正确的方法。

查询的解释计划显示了正在发生的事情。

解析器重写 fetch... 子句 - 它将解析 row_number 添加到 select 列表,并使用带有行号过滤器的外部查询。它将 unique 指令(select 中的 distinct 指令)推入子查询,这不是有效的转换;在 Oracle 的 fetch....

实现中,我认为这是一个明显的 bug

解释计划显示了解析器在其中应用 unique 并添加分析 row_number() 创建内联视图的步骤。它不显示投影(视图中包含哪些列),并且 - 关键 - 它适用于 unique 的内容。一点点实验给出了答案:它将 unique 应用于 customer_namelast_sales_date.

组合

这可能已被报告并可能在最近的版本中得到修复 - 您的 Oracle 版本是多少?