引入:
在实际操作中,俺写了这样一个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
子句,不知道按照啥条件又排序了,导致了上一次排序失效。
所以在用到JSON_ARRAYAGG()
函数且需要排序时,把排序写在JSON_ARRAYAGG()
函数内才能达到想要的排序效果。
大大的乌龙~