oracle - 带有 ORDER BY NULL 的 LISTAGG 实际上用作订单标准是什么?

标签 oracle sql-order-by listagg

如果我这样做

SELECT LISTAGG( COLUMN_VALUE ) WITHIN GROUP ( ORDER BY NULL )   AS OrderByNULL,
       LISTAGG( COLUMN_VALUE ) WITHIN GROUP ( ORDER BY 1 )      AS OrderByCONST,
       LISTAGG( COLUMN_VALUE ) WITHIN GROUP ( ORDER BY ROWNUM ) AS OrderByROWNUM
FROM   TABLE( SYS.ODCIVARCHAR2LIST( '5', '222', '4' ) );

输出是:
ORDERBYNULL ORDERBYCONST ORDERBYROWNUM
----------- ------------ -------------
222,4,5     222,4,5      5,222,4

当使用 ORDER BY 和非确定性排序(NULL 或常量)时,查询似乎已经完成了字母数字排序,并且在使用 ORDER BY ROWNUM(确定性)时保持了输入顺序。

LISTAGG 文档指出:

The order_by_clause determines the order in which the concatenated values are returned. The function is deterministic only if the ORDER BY column list achieved unique ordering.



在查看 analytic functions 时,它指出:

Whenever the order_by_clause results in identical values for multiple rows, the function behaves as follows: [...] For all other analytic functions, the result depends on the window specification. If you specify a logical window with the RANGE keyword, then the function returns the same result for each of the rows. If you specify a physical window with the ROWS keyword, then the result is nondeterministic.



因此,据我从文档中可以看出,非确定性排序是可以预期的 - 但是,该函数根据字母数字排序而不是处理行的顺序(即 commonly held view )给出确定性输出.

这与其他分析函数的行为不同(使用带有 ROWS 关键字的物理窗口时):
SELECT LAST_VALUE( COLUMN_VALUE )
         OVER ( ORDER BY NULL   ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING )
         AS BYNULL,
       LAST_VALUE( COLUMN_VALUE )
         OVER ( ORDER BY 1      ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING )
         AS BYCONST,
       LAST_VALUE( COLUMN_VALUE )
         OVER ( ORDER BY ROWNUM ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING )
         AS BYROWNUM
FROM   TABLE( SYS.ODCIVARCHAR2LIST( '5', '222', '4' ) );

这为所有不同的排序提供了一致的输出:
BYNULL BYCONST BYROWNUM
------ ------- --------
4      4       4
4      4       4
4      4       4

是否有官方文档说明当 LISTAGG 提供非确定性排序时如何应用排序?

注意:ORDER BY NULL 的行为被注释在 here 上,说明:

In this example, the elements have been aggregated alphabetically, despite the NULL ordering clause. This appears to be the default behaviour when using a constant ORDER BY expression



但这只是对非 Oracle 站点中的行为的评论。

最佳答案

顺序可能取决于许多因素,包括查询的执行计划、实例的配置、数据库的版本(如果您使用的是 exadata)。

如果您没有给 oracle 任何特定的数据排序标准,您就不能指望任何特定的排序,即使从您的试验中,您似乎以特定方式对数据进行了一致的排序。

根据 Oracle documentation for listagg :

  • order_by_clause 确定返回连接值的顺序。仅当 ORDER BY 列列表实现唯一排序时,该函数才是确定性的。
  • 关于oracle - 带有 ORDER BY NULL 的 LISTAGG 实际上用作订单标准是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35747417/

    相关文章:

    pandas - 如何在一次遍历行中将多列聚合为集合

    sql - 当查询包含 GROUP BY 子句时 ORACLE 中的前 10 行

    oracle - 从oracle中的日期获取财政年度

    sql - 你如何使用 SELECT WHERE IN() 保持顺序?

    mysql - 如何按每列不同优先级的多列排序?

    python - Django queryset order_by 日期接近今天

    .net - 密码过期

    c# - mscorlib.dll 中出现类型为 System.TypeInitializationException 的未处理异常

    oracle - 如何将 SELECT LISTAGG 值插入到 varchar 变量

    sql - ORACLE 中的 LISTAGG