Puoi farlo usando query gerarchiche:eccone una usando il vecchio stile connect by
:
WITH your_table AS (SELECT 1 ID, 'AL' state FROM dual UNION ALL
SELECT 1 ID, 'AZ' state FROM dual UNION ALL
SELECT 1 ID, 'MI' state FROM dual UNION ALL
SELECT 2 ID, 'TX' state FROM dual UNION ALL
SELECT 2 ID, 'TN' state FROM dual UNION ALL
SELECT 2 ID, 'MO' state FROM dual UNION ALL
SELECT 2 ID, 'ND' state FROM dual UNION ALL
SELECT 3 ID, 'OH' state FROM dual)
SELECT ID,
state,
ltrim(SYS_CONNECT_BY_PATH(state, ','), ',') combinations,
LEVEL
FROM (SELECT id,
state,
count(*) OVER (PARTITION BY id) state_cnt
FROM your_table)
WHERE state_cnt = 1
OR (state_cnt > 1 AND LEVEL > 1)
CONNECT BY PRIOR ID = ID
AND PRIOR state < state
AND PRIOR sys_guid() IS NOT NULL;
ID STATE COMBINATIONS LEVEL
---------- ----- ------------ ----------
1 AZ AL,AZ 2
1 MI AL,AZ,MI 3
1 MI AL,MI 2
1 MI AZ,MI 2
2 TX TN,TX 2
2 TX MO,TX 2
2 TN MO,TN 2
2 TX MO,TN,TX 3
2 ND MO,ND 2
2 TX MO,ND,TX 3
2 TN MO,ND,TN 3
2 TX MO,ND,TN,TX 4
2 TX ND,TX 2
2 TN ND,TN 2
2 TX ND,TN,TX 3
3 OH OH 1
Il prior sys_guid() is not null
la condizione nella clausola connect by è necessaria per garantire che stiamo scorrendo le righe corrette (se dovessi ometterlo, il risultato conterrebbe molte righe extra).
Ho escluso le righe con un solo stato nell'output, tranne se l'ID elencava solo un singolo stato. Potresti o meno voler includere singoli stati nell'output, nel qual caso puoi rimuovere completamente i predicati.