What does LISTAGG with ORDER BY NULL actually use as the order criteria?

耗尽温柔 提交于 2019-11-27 14:50:54

问题


If I do

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' ) );

The output is:

ORDERBYNULL ORDERBYCONST ORDERBYROWNUM
----------- ------------ -------------
222,4,5     222,4,5      5,222,4

The query appears to have done an alphanumerical sort when using ORDER BY with non-deterministic ordering (NULL or a constant) and has maintained the input order when using ORDER BY ROWNUM (deterministic).

The LISTAGG documentation states that:

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.

And when looking at analytic functions it states that:

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.

So as far as I can tell from the documentation a non-deterministic ordering is to be expected - however, the function gives a deterministic output based on an alphanumerical sort and not on the order in which the rows are processed (which is the commonly held view).

This is different to the behaviour of other analytic functions (when using a physical window with the ROWS keyword):

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' ) );

Which gives a consistent output for all the different orderings:

BYNULL BYCONST BYROWNUM
------ ------- --------
4      4       4
4      4       4
4      4       4

Is there official documentation for how an ordering is applied when LISTAGG is supplied a non-deterministic ordering?

Note: The behaviour of ORDER BY NULL is commented on here stating:

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

But this is just an comment on the behaviour in a non-Oracle site.


回答1:


Possibly the order will depend on many factor, including the execution plan of the query, the configuration of your instance, the version of the database, if you are on exadata or not.

If you are not giving oracle any specific criteria to order the data you can't count on any specific ordering, even if from your trials you seem to get the data consistently sorted in a specific way.

According to Oracle documentation for 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.


来源:https://stackoverflow.com/questions/35747417/what-does-listagg-with-order-by-null-actually-use-as-the-order-criteria

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!