If there is a table below, where the number of rows for each I value is variable
SQL code
- Sql> SELECT * from t;
- I A D
- ---------- ---------- -------------------
- 1 b 2008-03-27 10:55:42
- 1 a 2008-03-27 10:55:46
- 1 D 2008-03-27 10:55:30
- 2 Z 2008-03-27 10:55:55
- 2 T 2008-03-27 10:55:59
- ---to get the following result, note that the string needs to be sorted by the time of column D:
- 1 d,b,a
- 2 z,t
This is a more typical row and column conversion, there are several ways to implement
1. Custom Function Implementations
SQL code
- Create or replace function My_concat (n number)
- return VARCHAR2
- Is
- Type typ_cursor is ref cursor;
- V_cursor Typ_cursor;
- V_temp VARCHAR2 (10);
- V_result varchar2 (4000): = ";
- V_sql VARCHAR2 (200);
- Begin
- V_sql: = ' Select a from t where i= ' | | | n | | ' ORDER by d ';
- Open v_cursor for v_sql;
- Loop
- fetch v_cursor into v_temp;
- Exit when V_cursor%notfound;
- V_result: = V_result | | ', ' | | | v_temp;
- end Loop;
- return substr (v_result,2);
- End
- sql> Select I,my_concat (i) from the T Group by I;
- I my_concat (i)
- ---------- --------------------
- 1 d,b,a
- 2 z,t
Although this approach can achieve the requirements, but if the data volume of table t is large, I the value of a lot of cases, because for each I value to execute a SELECT, scan and sort the number of times and the value of I is proportional to the performance will be very poor.
2. Using Sys_connect_by_path
SQL code
- Select I,ltrim (max (Sys_connect_by_path (A,', ')),', ') a
- From
- (
- Select I,a,d,min (d) over (partition by i) d_min,
- (Row_number () over (order by I,d)) + (Dense_rank () over (order by i)) numid
- From T
- )
- Start with d=d_min connect by numid-1=prior numid
- Group by I;
From the execution plan, this method only needs to scan two tables, more efficient than the method of custom functions, especially when the data volume in the table is large:
3. Using Wm_sys.wm_concat
This function can also implement a similar row-and-column conversion requirement, but there seems to be no way to sort directly according to the other columns, so you need to first order through a subquery or temporary table:
SQL code
- sql> Select I,wmsys.wm_concat (a) from T Group by I;
- I Wmsys. Wm_concat (A)
- ---------- --------------------
- 1 b,a,d
- 2 z,t
- sql> Select I,wmsys.wm_concat (a)
- 2 from
- 3 (select * from t order by I,d)
- 4 GROUP by I;
- I Wmsys. Wm_concat (A)
- ---------- --------------------
- 1 d,b,a
- 2 z,t
On the execution plan, only one table scan is required, but the function is encrypted, and the execution plan does not show the action inside the function.