Having the following table my_tabe:

M01 |   1
M01 |   2
M02 |   1

I want to query over it in order to obtain:

M01 |   1,2
M02 |   1

I managed to get close using the following query:

with my_tabe as
(
    select 'M01' as scycle, '1' as sdate from dual union
    select 'M01' as scycle, '2' as sdate from dual union
    select 'M02' as scycle, '1' as sdate from dual
)
SELECT scycle, ltrim(sys_connect_by_path(sdate, ','), ',')
FROM
(
    select scycle, sdate, rownum rn
    from my_tabe
    order by 1 desc
)
START WITH rn = 1
CONNECT BY PRIOR rn = rn - 1

Yielding:

SCYCLE      |   RES
M02         |   1,2,1
M01         |   1,2

Which is wrong. It's seems I'm close, but I'm afraid I don't what's the next step...

Any tips?

有帮助吗?

解决方案

You need to restrict your connect by to the same scycle value, and also count the number of matches and filter on that to avoid seeing intermediate results.

with my_tabe as
(
    select 'M01' as scycle, '1' as sdate from dual union
    select 'M01' as scycle, '2' as sdate from dual union
    select 'M02' as scycle, '1' as sdate from dual
)
select scycle, ltrim(sys_connect_by_path(sdate, ','), ',')
from
(
    select distinct sdate,
        scycle,
        count(1) over (partition by scycle) as cnt,
        row_number() over (partition by scycle order by sdate) as rn
    from my_tabe
)
where rn = cnt
start with rn = 1
connect by prior rn + 1 = rn
and prior scycle = scycle
/

SCYCLE LTRIM(SYS_CONNECT_BY_PATH(SDATE,','),',')
------ -----------------------------------------
M01    1,2
M02    1

If you're on 11g you can use the built-in LISTAGG function instead:

with my_tabe as
(
    select 'M01' as scycle, '1' as sdate from dual union
    select 'M01' as scycle, '2' as sdate from dual union
    select 'M02' as scycle, '1' as sdate from dual
)
select scycle, listagg (sdate, ',') 
within group (order by sdate) res
from my_tabe
group by scycle
/ 

Both approaches (and others) are shown here.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top