如果您在已排序的 CTE 上执行简单的 SELECT-WHERE,您的结果是否保证仍处于相同顺序,只是经过过滤?
If you do a simple SELECT-WHERE on a CTE that is already sorted, are your results guaranteed to still be in that same order, just filtered?
想知道 expected/deterministic 从 Oracle 11g 为基于排序的 CTE 的查询排序输出。
考虑这个(为方便起见而极其简化的)示例 SQL 查询。再次注意 CTE 中有一个 ORDER BY
子句。
WITH SortedArticles as (
SELECT. *
FROM Articles
ORDER BY DatePublished
)
SELECT *
FROM SortedArticles
WHERE Author = 'Joe';
是否可以假设输出的行保证与 CTE 的顺序相同,还是我必须再次对它们重新排序?
同样,这是一个过于简化的示例,但它包含了我要问的重要部分。他们是...
- CTE 排序
- 最后的
SELECT
语句仅针对 CTE 选择,没有其他(没有连接等),并且
- 最后的
SELECT
语句只指定了一个WHERE
子句。纯属过滤语句。
不,不保证结果与子查询中的顺序相同。从来没有,永远不会。您可能会观察到某种行为,尤其是当 CTE 被具体化时,您可以尝试使用 /*+ MATERIALIZE */
和 /*+ INLINE */
等优化器提示来影响它。然而,查询优化器的行为还取决于数据量、IO v cpu 速度,最重要的是取决于数据库版本。例如,Oracle 12.2 引入了一个名为 "In-Memory Cursor Duration Temp Table" 的特性,它试图加速像您这样的查询,而不保留子查询中的顺序。
我赞同@Nick 在子查询中添加行号字段的建议。
简短的回答是否定的。 保证 排序的唯一方法是在外部查询中使用 ORDER BY
子句。但是在那种情况下不需要对CTE中的结果进行排序。
但是,如果排序表达式很复杂,并且您需要 在派生的 CTE 中排序(例如,因为使用 OFFSET/FETCH
或 ROWNUM
),您可以根据排序标准向原始 CTE 添加行号字段,然后仅按该行号对派生的 CTE 进行排序,从而简化后续排序。例如:
WITH SortedArticles as (
SELECT *,
ROW_NUMBER() OVER (ORDER BY DatePublished) AS rn
FROM Articles
)
SELECT *
FROM SortedArticles
WHERE Author = 'Joe'
ORDER BY rn
想知道 expected/deterministic 从 Oracle 11g 为基于排序的 CTE 的查询排序输出。
考虑这个(为方便起见而极其简化的)示例 SQL 查询。再次注意 CTE 中有一个 ORDER BY
子句。
WITH SortedArticles as (
SELECT. *
FROM Articles
ORDER BY DatePublished
)
SELECT *
FROM SortedArticles
WHERE Author = 'Joe';
是否可以假设输出的行保证与 CTE 的顺序相同,还是我必须再次对它们重新排序?
同样,这是一个过于简化的示例,但它包含了我要问的重要部分。他们是...
- CTE 排序
- 最后的
SELECT
语句仅针对 CTE 选择,没有其他(没有连接等),并且 - 最后的
SELECT
语句只指定了一个WHERE
子句。纯属过滤语句。
不,不保证结果与子查询中的顺序相同。从来没有,永远不会。您可能会观察到某种行为,尤其是当 CTE 被具体化时,您可以尝试使用 /*+ MATERIALIZE */
和 /*+ INLINE */
等优化器提示来影响它。然而,查询优化器的行为还取决于数据量、IO v cpu 速度,最重要的是取决于数据库版本。例如,Oracle 12.2 引入了一个名为 "In-Memory Cursor Duration Temp Table" 的特性,它试图加速像您这样的查询,而不保留子查询中的顺序。
我赞同@Nick 在子查询中添加行号字段的建议。
简短的回答是否定的。 保证 排序的唯一方法是在外部查询中使用 ORDER BY
子句。但是在那种情况下不需要对CTE中的结果进行排序。
但是,如果排序表达式很复杂,并且您需要 在派生的 CTE 中排序(例如,因为使用 OFFSET/FETCH
或 ROWNUM
),您可以根据排序标准向原始 CTE 添加行号字段,然后仅按该行号对派生的 CTE 进行排序,从而简化后续排序。例如:
WITH SortedArticles as (
SELECT *,
ROW_NUMBER() OVER (ORDER BY DatePublished) AS rn
FROM Articles
)
SELECT *
FROM SortedArticles
WHERE Author = 'Joe'
ORDER BY rn