引入:
在实际操作中,俺写了这样一个Funtcion:
FUNCTION fun_get_xxx(v_param_one VARCHAR2) RETURN CLOB AS
v_OUTPUT CLOB;
BEGIN
WITH temp_table AS (
SELECT * FROM (
( SELECT one.action_id,
two.log_time
FROM table_one one
LEFT JOIN table_two two on two.action_id = one.action_id
WHERE one.action_id = v_param_one
)
UNION
( SELECT one.action_id,
two.log_time
FROM table_three three
LEFT JOIN table_four four on four.action_id = three.action_id
WHERE three.action_id = v_param_one)
)
)
ORDER BY log_time DESC
SELECT JSON_OBJECT(
'numOfRecords' VALUE count(temp_table .action_id),
'records' VALUE (
JSON_ARRAYAGG(
JSON_OBJECT(
'actionId' VALUE temp_table.action_id,
'logTime' VALUE temp_table.log_time
)
)
) format json returning clob
)
INTO v_OUTPUT
from temp_table;
RETURN v_OUTPUT;
END fun_get_xxx;
在WITH
子句中,对数据进行了关于log_time
列的ORDER BY
排序,
因为中间用了UNION
,因此是把ORDER BY
子句放到了外层的SELECT
语句中的,因此能保证排序不受UNION
影响,
但是根据返回的结果显示,关于log_time
的排序是失败的,但它并不是没有排序,而是关于action_id
排序,
试过把ORDER BY
子句放到UNION
语句中,也不行,
然后怀疑上了那两个JSON封装函数头上,最终在JSON_ARRAYAGG()
函数上找到了解决办法。
最终修改成如下:
-- 省略...
SELECT JSON_OBJECT(
'numOfRecords' VALUE count(temp_table .action_id),
'records' VALUE (
JSON_ARRAYAGG(
JSON_OBJECT(
'actionId' VALUE temp_table.action_id,
'logTime' VALUE temp_table.log_time
)
) ORDER BY log_time DESC -- 把排序放到了这里
) format json returning clob
)
-- 省略...
原因:
先看官方文档关于JSON_ARRAYAGG()
函数的结构说明:
可以看到JSON_ARRAYAGG()
函数的结构是可以包含ORDER BY
子句的。
The JSON_ARRAYAGG function is used to aggregate data from multiple rows into a single JSON array. When using this function, the data will be ordered by the unique key because the function automatically orders the data based on the order of the rows in the result set.
大概意思:
JSON_ARRAYAGG函数用于将多行数据聚合成一个JSON数组。在使用此函数时,数据将按照唯一键进行排序,因为该函数会根据结果集中行的顺序自动对数据进行排序。
所以当JSON_ARRAYAGG()
函数里面没有指定ORDER BY
子句的时候,他就不能保证顺序问题,不清楚在这个封装过程它有没有对数据进行重新排序。
按说在WITH
中的temp_table
应该是已经排好序了的,因为俺单独把那一组语句拉出来跑,得到的结果排序没问题,非常可能在进行json封装的过程中,因为没有指定ORDER BY
子句,不知道按照啥条件又排序了,导致了上一次排序失效。
问了问 chatGPT:
it is possible that the ordering is lost when aggregating the results into a JSON array using the json_arrayagg function
当使用json_arrayagg函数将结果聚合到JSON数组中时,可能会丢失原来的排序。
The reason why aggregating the results into a JSON array using the json_arrayagg function can lose the ordering is because the function does not guarantee any specific order of the elements in the resulting array. The order of the elements may be affected by various factors such as the order in which they are retrieved from the database, how they are processed by the function, and other internal implementation details.
使用json_arrayagg函数将结果聚合到JSON数组中可能会失去排序的原因是因为该函数不能保证结果数组中元素的任何特定顺序。元素的顺序可能受到各种因素的影响,比如从数据库中检索元素的顺序、函数处理元素的方式以及其他内部实现细节。
所以在用到JSON_ARRAYAGG()
函数且需要排序时,把排序写在JSON_ARRAYAGG()
函数内才能达到想要的排序效果。
大大的乌龙~