Oracle兼容-函数-LISTAGG()函数
1. 语法
1. LISTAGG ( [ { ALL | DISTINCT } ] measure_expr [ , 'delimiter' ] )
2. [ WITHIN GROUP ( order_by_clause ) ]
3. [ OVER query_partition_clause ]
5. query_partition_clause := ( PARTITION BY column_name [,...] )
2. 定义和用法
参数说明:
measure_expr可以是列,常量或基于列的表达式。delimiter分隔符,可以是 ‘’、字符串文字、数字、浮点等。order_by_clauseORDER BY子句决定了列值被拼接的顺序。- 当
ALL及DISTINCT都未指定时,视为ALL。 OVER query_partition_clause不存在时,视为 聚合(AGGREGATE) 函数。反之,视为 分析(ANALYTIC) 函数。- 目前不支持聚合类函数嵌套使用,例如:
1. greatsql> SELECT listagg(sum(id)) FROM t1 GROUP BY id;
2. ERROR 1111 (HY000): Invalid use of group function
3. Oracle兼容说明
- 在GreatSQL中的
LISTAGG()函数语法参考 Oracle 19c 版本用法,与 Oracle 11r2 版本的WITHIN GROUP用法部分有差异。 - 目前尚未支持
LISTAGG OVERFLOW语法,仍沿用GreatSQL中的group_concat_max_len选项限制方式。 - 分隔符
delimiter目前只支持字符常量,不支持使用 session/global 设定或运算式(注意: 会将数字常量转换为字符常量,转换时可能会因浮点精度或格式问题,不一定如预期呈现,因此建议直接使用字符常量)。
4. 示例
说明:GreatSQL中返回结果顺序与Oracle顺序可能会因为使用字符集不同存在排序差异。
1. -- 创建测试表,填充测试数据
2. greatsql> CREATE TABLE plan1 (
3. id int PRIMARY KEY,
4. name VARCHAR(255)
5. );
7. greatsql> CREATE TABLE plandetail(
8. id INT PRIMARY KEY,
9. name VARCHAR(255),
10. state INT,
11. planid INT
12. );
14. greatsql> INSERT INTO plan1 VALUES(1,'计划一'), (2,'计划二'), (3,'计划三');
16. greatsql> INSERT INTO plandetail VALUES(1,'明细一',0,1), (2,'明细2',1,1), (3,'明细3',1,1);
18. greatsql> INSERT INTO plandetail VALUES(4,'明细一',0,2), (5,'明细2',0,2), (6,'明细3',1,2);
20. greatsql> INSERT INTO plandetail VALUES(7,'明细一',1,3), (8,'明细2',1,3), (9,'明细3',1,3);
1. 分别测试 GROUP_CONCAT() 和 LISTAGG()
1. greatsql> SELECT t1.name ,GROUP_CONCAT(t2.name ORDER BY planid ASC SEPARATOR ',') FROM plan1 t1
2. LEFT JOIN plandetail t2
3. ON t1.id = t2.planid
4. GROUP BY t1.name;
5. +-----------+---------------------------------------------------------+
6. | name | GROUP_CONCAT(t2.name ORDER BY planid ASC SEPARATOR ',') |
7. +-----------+---------------------------------------------------------+
8. | 计划一 | 明细一,明细2,明细3 |
9. | 计划三 | 明细一,明细2,明细3 |
10. | 计划二 | 明细一,明细2,明细3 |
11. +-----------+---------------------------------------------------------+
13. greatsql> SELECT t1.name ,LISTAGG(t2.name,',') WITHIN GROUP (ORDER BY t2.planid ASC) FROM plan1 t1
14. LEFT JOIN plandetail t2
15. ON t1.id = t2.planid
16. GROUP BY t1.name;
17. +-----------+-------------------------------------------------------------+
18. | name | LISTAGG(t2.name,',') WITHIN GROUP (ORDER BY t2.planid ASC) |
19. +-----------+-------------------------------------------------------------+
20. | 计划一 | 明细一,明细2,明细3 |
21. | 计划三 | 明细一,明细2,明细3 |
22. | 计划二 | 明细一,明细2,明细3 |
23. +-----------+-------------------------------------------------------------+
25. greatsql> SELECT t1.name ,LISTAGG(t2.name,'') WITHIN GROUP (ORDER BY t2.planid ASC) FROM plan1 t1
26. LEFT JOIN plandetail t2
27. ON t1.id = t2.planid
28. GROUP BY t1.name;
29. +-----------+------------------------------------------------------------+
30. | name | LISTAGG(t2.name,'') WITHIN GROUP (ORDER BY t2.planid ASC) |
31. +-----------+------------------------------------------------------------+
32. | 计划一 | 明细一明细2明细3 |
33. | 计划三 | 明细一明细2明细3 |
34. | 计划二 | 明细一明细2明细3 |
35. +-----------+------------------------------------------------------------+
37. greatsql> SELECT t1.name ,LISTAGG(t2.name,':') WITHIN GROUP (ORDER BY t2.planid ASC) FROM plan1 t1
38. LEFT JOIN plandetail t2
39. ON t1.id = t2.planid
40. GROUP BY t1.name;
41. +-----------+-------------------------------------------------------------+
42. | name | LISTAGG(t2.name,':') WITHIN GROUP (ORDER BY t2.planid ASC) |
43. +-----------+-------------------------------------------------------------+
44. | 计划一 | 明细一:明细2:明细3 |
45. | 计划三 | 明细一:明细2:明细3 |
46. | 计划二 | 明细一:明细2:明细3 |
47. +-----------+-------------------------------------------------------------+
49. greatsql> SELECT t1.name ,LISTAGG(t2.name,'\'') WITHIN GROUP (ORDER BY t2.planid ASC) FROM plan1 t1
50. LEFT JOIN plandetail t2
51. ON t1.id = t2.planid
52. GROUP BY t1.name;
53. +-----------+--------------------------------------------------------------+
54. | name | LISTAGG(t2.name,'\'') WITHIN GROUP (ORDER BY t2.planid ASC) |
55. +-----------+--------------------------------------------------------------+
56. | 计划一 | 明细一'明细2'明细3 |
57. | 计划三 | 明细一'明细2'明细3 |
58. | 计划二 | 明细一'明细2'明细3 |
59. +-----------+--------------------------------------------------------------+
61. greatsql> SELECT t1.name ,LISTAGG(t2.name,1) WITHIN GROUP (ORDER BY t2.planid ASC) FROM plan1 t1
62. LEFT JOIN plandetail t2
63. ON t1.id = t2.planid
64. GROUP BY t1.name;
65. +-----------+-----------------------------------------------------------+
66. | name | LISTAGG(t2.name,1) WITHIN GROUP (ORDER BY t2.planid ASC) |
67. +-----------+-----------------------------------------------------------+
68. | 计划一 | 明细一1明细21明细3 |
69. | 计划三 | 明细一1明细21明细3 |
70. | 计划二 | 明细一1明细21明细3 |
71. +-----------+-----------------------------------------------------------+
73. greatsql> SELECT t1.name ,LISTAGG(t2.name,-1) WITHIN GROUP (ORDER BY t2.planid ASC) FROM plan1 t1
74. LEFT JOIN plandetail t2
75. ON t1.id = t2.planid
76. GROUP BY t1.name;
77. +-----------+------------------------------------------------------------+
78. | name | LISTAGG(t2.name,-1) WITHIN GROUP (ORDER BY t2.planid ASC) |
79. +-----------+------------------------------------------------------------+
80. | 计划一 | 明细一-1明细2-1明细3 |
81. | 计划三 | 明细一-1明细2-1明细3 |
82. | 计划二 | 明细一-1明细2-1明细3 |
83. +-----------+------------------------------------------------------------+
85. greatsql> SELECT t1.name ,LISTAGG(t2.name,1.0000000001) WITHIN GROUP (ORDER BY t2.planid ASC) FROM plan1 t1
86. LEFT JOIN plandetail t2
87. ON t1.id = t2.planid
88. GROUP BY t1.name;
89. +-----------+----------------------------------------------------------------------+
90. | name | LISTAGG(t2.name,1.0000000001) WITHIN GROUP (ORDER BY t2.planid ASC) |
91. +-----------+----------------------------------------------------------------------+
92. | 计划一 | 明细一1.0000000001明细21.0000000001明细3 |
93. | 计划三 | 明细一1.0000000001明细21.0000000001明细3 |
94. | 计划二 | 明细一1.0000000001明细21.0000000001明细3 |
95. +-----------+----------------------------------------------------------------------+
97. greatsql> SELECT t1.name ,LISTAGG(t2.name,-1.0000000001) WITHIN GROUP (ORDER BY t2.planid ASC) FROM plan1 t1
98. LEFT JOIN plandetail t2
99. ON t1.id = t2.planid
100. GROUP BY t1.name;
101. +-----------+-----------------------------------------------------------------------+
102. | name | LISTAGG(t2.name,-1.0000000001) WITHIN GROUP (ORDER BY t2.planid ASC) |
103. +-----------+-----------------------------------------------------------------------+
104. | 计划一 | 明细一-1.0000000001明细2-1.0000000001明细3 |
105. | 计划三 | 明细一-1.0000000001明细2-1.0000000001明细3 |
106. | 计划二 | 明细一-1.0000000001明细2-1.0000000001明细3 |
107. +-----------+-----------------------------------------------------------------------+
109. greatsql> SELECT t1.name ,LISTAGG(t2.name,'|分割|') WITHIN GROUP (ORDER BY t2.planid ASC) FROM plan1 t1
110. LEFT JOIN plandetail t2
111. ON t1.id = t2.planid
112. GROUP BY t1.name;
113. +-----------+--------------------------------------------------------------------+
114. | name | LISTAGG(t2.name,'|分割|') WITHIN GROUP (ORDER BY t2.planid ASC) |
115. +-----------+--------------------------------------------------------------------+
116. | 计划一 | 明细一|分割|明细2|分割|明细3 |
117. | 计划三 | 明细一|分割|明细2|分割|明细3 |
118. | 计划二 | 明细一|分割|明细2|分割|明细3 |
119. +-----------+--------------------------------------------------------------------+
2. 测试分析性查询
1. -- 创建测试表,填充测试数据
2. greatsql> CREATE TABLE p (population INT, nation CHAR(20), city CHAR(20));
3. greatsql> INSERT INTO p VALUES (500, 'China','Guangzhou'),
4. (1500, 'China','Shanghai'),
5. (500, 'China','Beijing'),
6. (1000, 'USA','New York'),
7. (500, 'USA','Bostom'),
8. (500, 'Japan','Tokyo');
10. -- 测试LISTAGG over partition
11. greatsql> SELECT
12. nation, LISTAGG(p.city, ',') OVER (PARTITION BY nation ) la_a_city
13. FROM p;
14. +--------+----------------------------+
15. | nation | la_a_city |
16. +--------+----------------------------+
17. | China | Guangzhou,Shanghai,Beijing |
18. | China | Guangzhou,Shanghai,Beijing |
19. | China | Guangzhou,Shanghai,Beijing |
20. | Japan | Tokyo |
21. | USA | New York,Bostom |
22. | USA | New York,Bostom |
23. +--------+----------------------------+
25. greatsql> SELECT
26. nation, city, LISTAGG(p.city, ',') OVER (PARTITION BY nation ) la_a_city
27. FROM p;
28. +--------+-----------+----------------------------+
29. | nation | city | la_a_city |
30. +--------+-----------+----------------------------+
31. | China | Guangzhou | Guangzhou,Shanghai,Beijing |
32. | China | Shanghai | Guangzhou,Shanghai,Beijing |
33. | China | Beijing | Guangzhou,Shanghai,Beijing |
34. | Japan | Tokyo | Tokyo |
35. | USA | New York | New York,Bostom |
36. | USA | Bostom | New York,Bostom |
37. +--------+-----------+----------------------------+
39. greatsql> SELECT
40. nation, city, LISTAGG(p.city, ',') WITHIN GROUP (ORDER BY city ASC)
41. OVER (PARTITION BY nation ) la_a_city
42. FROM p;
43. +--------+-----------+----------------------------+
44. | nation | city | la_a_city |
45. +--------+-----------+----------------------------+
46. | China | Beijing | Beijing,Guangzhou,Shanghai |
47. | China | Guangzhou | Beijing,Guangzhou,Shanghai |
48. | China | Shanghai | Beijing,Guangzhou,Shanghai |
49. | Japan | Tokyo | Tokyo |
50. | USA | Bostom | Bostom,New York |
51. | USA | New York | Bostom,New York |
52. +--------+-----------+----------------------------+
54. -- 测试其他分析型函数
55. greatsql> SELECT
56. SUM(population) OVER (PARTITION BY nation) population,
57. LISTAGG(p.city, ',') OVER (PARTITION BY nation) la_a_city
58. FROM p;
59. +------------+----------------------------+
60. | population | la_a_city |
61. +------------+----------------------------+
62. | 2500 | Guangzhou,Shanghai,Beijing |
63. | 2500 | Guangzhou,Shanghai,Beijing |
64. | 2500 | Guangzhou,Shanghai,Beijing |
65. | 500 | Tokyo |
66. | 1500 | New York,Bostom |
67. | 1500 | New York,Bostom |
68. +------------+----------------------------+
70. greatsql> SELECT
71. SUM(population) OVER (PARTITION BY nation) population,
72. LISTAGG(p.city, ',') WITHIN GROUP (ORDER BY city ASC)
73. OVER (PARTITION BY nation ) la_a_city
74. FROM p;
75. +------------+----------------------------+
76. | population | la_a_city |
77. +------------+----------------------------+
78. | 2500 | Beijing,Guangzhou,Shanghai |
79. | 2500 | Beijing,Guangzhou,Shanghai |
80. | 2500 | Beijing,Guangzhou,Shanghai |
81. | 500 | Tokyo |
82. | 1500 | Bostom,New York |
83. | 1500 | Bostom,New York |
84. +------------+----------------------------+
86. greatsql> SELECT
87. SUM(population) OVER (PARTITION BY nation ORDER BY city ASC) population,
88. LISTAGG(p.city, ',') OVER (PARTITION BY nation ) la_a_city
89. FROM p;
90. +------------+----------------------------+
91. | population | la_a_city |
92. +------------+----------------------------+
93. | 500 | Beijing,Guangzhou,Shanghai |
94. | 1000 | Beijing,Guangzhou,Shanghai |
95. | 2500 | Beijing,Guangzhou,Shanghai |
96. | 500 | Tokyo |
97. | 500 | Bostom,New York |
98. | 1500 | Bostom,New York |
99. +------------+----------------------------+
问题反馈
联系我们
扫码关注微信公众号

