Eventually, I've got it )
It was an interesting task for me to solve it using only SQL:
B N SORTED BOOL
---------- ---------- -------------------------------------------------------------------------------- -----
1 1 [a],[b],[c] true
1 2 [ccc],[rr],[vvv] false
1 3 [] true
1 step: union two tables:
SQL> with
2 t1 as (
3 select 1 n, 'c,b,a' c from dual
4 union all
5 select 2 n, 'vvv,ccc,rr' c from dual
6 union all
7 select 3 n, null c from dual),
8 t2 as (
9 select 1 n, 'a,b,c' c from dual
10 union all
11 select 2 n, 'ccc,rr,125' c from dual
12 union all
13 select 3 n, null c from dual),
14 t12 as (select 1 b, n, c from t1 union all select 2 b, n, c from t2)
15 select * from t12
16 /
B N C
---------- ---------- ----------
1 1 c,b,a
1 2 vvv,ccc,rr
1 3
2 1 a,b,c
2 2 ccc,rr,125
2 3
6 rows selected
2 step: count separators:
SQL> with
2 t1 as (
3 select 1 n, 'c,b,a' c from dual
4 union all
5 select 2 n, 'vvv,ccc,rr' c from dual
6 union all
7 select 3 n, null c from dual),
8 t2 as (
9 select 1 n, 'a,b,c' c from dual
10 union all
11 select 2 n, 'ccc,rr,125' c from dual
12 union all
13 select 3 n, null c from dual),
14 t12 as (select 1 b, n, c from t1 union all select 2 b, n, c from t2),
15 t as (select b, n, c, nvl(length(regexp_replace(c, '[^,]+')) + 1, 1) cnt from t12)
16 select * from t
17 /
B N C CNT
---------- ---------- ---------- ----------
1 1 c,b,a 3
1 2 vvv,ccc,rr 3
1 3 1
2 1 a,b,c 3
2 2 ccc,rr,125 3
2 3 1
6 rows selected
3 step: calc border values
SQL> with
2 t1 as (
3 select 1 n, 'c,b,a' c from dual
4 union all
5 select 2 n, 'vvv,ccc,rr' c from dual
6 union all
7 select 3 n, null c from dual),
8 t2 as (
9 select 1 n, 'a,b,c' c from dual
10 union all
11 select 2 n, 'ccc,rr,125' c from dual
12 union all
13 select 3 n, null c from dual),
14 t12 as (select 1 b, n, c from t1 union all select 2 b, n, c from t2),
15 t as (select b, n, c, nvl(length(regexp_replace(c, '[^,]+')) + 1, 1) cnt from t12),
16 tbrd as (select b, n, c, cnt, sum(cnt) over (order by b,n) brd from t)
17 select * from tbrd
18 /
B N C CNT BRD
---------- ---------- ---------- ---------- ----------
1 1 c,b,a 3 3
1 2 vvv,ccc,rr 3 6
1 3 1 7
2 1 a,b,c 3 10
2 2 ccc,rr,125 3 13
2 3 1 14
6 rows selected
4 step: generate new query for rows
SQL> with
2 t1 as (
3 select 1 n, 'c,b,a' c from dual
4 union all
5 select 2 n, 'vvv,ccc,rr' c from dual
6 union all
7 select 3 n, null c from dual),
8 t2 as (
9 select 1 n, 'a,b,c' c from dual
10 union all
11 select 2 n, 'ccc,rr,125' c from dual
12 union all
13 select 3 n, null c from dual),
14 t12 as (select 1 b, n, c from t1 union all select 2 b, n, c from t2),
15 t as (select b, n, c, nvl(length(regexp_replace(c, '[^,]+')) + 1, 1) cnt from t12),
16 tbrd as (select b, n, c, cnt, sum(cnt) over (order by b,n) brd from t),
17 allrec as (select level lv from dual connect by level <= (select sum(cnt) from t))
18 select * from allrec
19 /
LV
----------
1
2
3
4
5
6
7
8
9
10
11
12
13
14
14 rows selected
5 step: main query
SQL> with
2 t1 as (
3 select 1 n, 'c,b,a' c from dual
4 union all
5 select 2 n, 'vvv,ccc,rr' c from dual
6 union all
7 select 3 n, null c from dual),
8 t2 as (
9 select 1 n, 'a,b,c' c from dual
10 union all
11 select 2 n, 'ccc,rr,125' c from dual
12 union all
13 select 3 n, null c from dual),
14 t12 as (select 1 b, n, c from t1 union all select 2 b, n, c from t2),
15 t as (select b, n, c, nvl(length(regexp_replace(c, '[^,]+')) + 1, 1) cnt from t12),
16 tbrd as (select b, n, c, cnt, sum(cnt) over (order by b,n) brd from t),
17 allrec as (select level lv from dual connect by level <= (select sum(cnt) from t)),
18 step5 as (select r.b, r.n, r.c, regexp_substr(c, '[^,]+', 1, r.brd - a.lv + 1) s from tbrd r, allrec a
19 where r.brd - a.lv between 0 and r.cnt - 1)
20 select * from step5
21 /
B N C S
---------- ---------- ---------- ----------
1 1 c,b,a a
1 1 c,b,a b
1 1 c,b,a c
1 2 vvv,ccc,rr rr
1 2 vvv,ccc,rr ccc
1 2 vvv,ccc,rr vvv
1 3
2 1 a,b,c c
2 1 a,b,c b
2 1 a,b,c a
2 2 ccc,rr,125 125
2 2 ccc,rr,125 rr
2 2 ccc,rr,125 ccc
2 3
14 rows selected
6 step: sorting values
SQL> with
2 t1 as (
3 select 1 n, 'c,b,a' c from dual
4 union all
5 select 2 n, 'vvv,ccc,rr' c from dual
6 union all
7 select 3 n, null c from dual),
8 t2 as (
9 select 1 n, 'a,b,c' c from dual
10 union all
11 select 2 n, 'ccc,rr,125' c from dual
12 union all
13 select 3 n, null c from dual),
14 t12 as (select 1 b, n, c from t1 union all select 2 b, n, c from t2),
15 t as (select b, n, c, nvl(length(regexp_replace(c, '[^,]+')) + 1, 1) cnt from t12),
16 tbrd as (select b, n, c, cnt, sum(cnt) over (order by b,n) brd from t),
17 allrec as (select level lv from dual connect by level <= (select sum(cnt) from t)),
18 step5 as (select r.b, r.n, r.c, regexp_substr(c, '[^,]+', 1, r.brd - a.lv + 1) s from tbrd r, allrec a
19 where r.brd - a.lv between 0 and r.cnt - 1),
20 step6 as (
21 select b, n, listagg('[' || s || ']', ',') within group (order by s) sorted
22 from step5
23 group by b, n)
24 select * from step6
25 /
B N SORTED
---------- ---------- --------------------------------------------------------------------------------
1 1 [a],[b],[c]
1 2 [ccc],[rr],[vvv]
1 3 []
2 1 [a],[b],[c]
2 2 [125],[ccc],[rr]
2 3 []
6 rows selected
7 step: result
SQL> with
2 t1 as (
3 select 1 n, 'c,b,a' c from dual
4 union all
5 select 2 n, 'vvv,ccc,rr' c from dual
6 union all
7 select 3 n, null c from dual),
8 t2 as (
9 select 1 n, 'a,b,c' c from dual
10 union all
11 select 2 n, 'ccc,rr,125' c from dual
12 union all
13 select 3 n, null c from dual),
14 t12 as (select 1 b, n, c from t1 union all select 2 b, n, c from t2),
15 t as (select b, n, c, nvl(length(regexp_replace(c, '[^,]+')) + 1, 1) cnt from t12),
16 tbrd as (select b, n, c, cnt, sum(cnt) over (order by b,n) brd from t),
17 allrec as (select level lv from dual connect by level <= (select sum(cnt) from t)),
18 step5 as (select r.b, r.n, r.c, regexp_substr(c, '[^,]+', 1, r.brd - a.lv + 1) s from tbrd r, allrec a
19 where r.brd - a.lv between 0 and r.cnt - 1),
20 step6 as (
21 select b, n, listagg('[' || s || ']', ',') within group (order by s) sorted
22 from step5
23 group by b, n)
24 select t.*, decode(
25 (select 1 from step6 z
26 where z.b = 2 and z.sorted = t.sorted and rownum < 2), 1, 'true', 'false') bool
27 from step6 t where b = 1
28 /
B N SORTED BOOL
---------- ---------- -------------------------------------------------------------------------------- -----
1 1 [a],[b],[c] true
1 2 [ccc],[rr],[vvv] false
1 3 [] true
Of course, it is much better to use functions, but, I just wanted to find a way using only SQL.
(2017-06-05: Added function)
Function can be:
create or replace function comparesepval(vArg1 in varchar2, vArg2 in varchar2) return number result_cache deterministic
as
type tpStore is table of number index by varchar2(32);
tStore1 tpStore;
tStore2 tpStore;
nCnt number;
vVal varchar2(32);
begin
if (vArg1 is null and vArg2 is null) or (vArg1 = vArg2) then
return 1;
end if;
if vArg1 is null then
return 0;
end if;
nCnt := nvl(length(regexp_replace(vArg1, '[^,]+')), 0) + 1;
if nCnt = 1 or nCnt <> nvl(length(regexp_replace(vArg2, '[^,]+')), 0) + 1 then -- vArg1 <> vArg2
return 0;
end if;
-- parse string
for i in 1..nCnt
loop
declare
procedure prcAgr(vArg in varchar2, tStore in out tpStore)
as
vVal varchar2(32) := nvl(regexp_substr(vArg, '(.*?)(,|$)', 1, i, null, 1), ','); -- ',' - for null
begin
tStore(vVal) := case when tStore.exists(vVal) then tStore(vVal) + 1 else 1 end;
end;
begin
prcAgr(vArg1, tStore1);
prcAgr(vArg2, tStore2);
end;
end loop;
if tStore1.count <> tStore2.count then
return 0;
end if;
vVal := tStore1.first;
loop
exit when vVal is null;
if not tStore2.exists(vVal) then
return 0;
end if;
if tStore2(vVal) <> tStore1(vVal) then
return 0;
end if;
vVal := tStore1.next(vVal);
end loop;
return 1;
end;
/
Test:
SQL> with tbl as (
2 select null c1, null c2 from dual union all
3 select 'a' c1, 'a' c2 from dual union all
4 select 'a' c1, 'b' c2 from dual union all
5 select 'a,a' c1, 'a,b' c2 from dual union all
6 select 'a,a' c1, 'a,b,a' c2 from dual union all
7 select 'a,a,b' c1, 'a,b,a' c2 from dual union all
8 select 'a,,b' c1, ',b,a' c2 from dual union all
9 select 'a,' c1, 'd,' c2 from dual
10 )
11 select comparesepval(c1, c2) c, c1, c2 from tbl;
C C1 C2
---------- ----- -----
1
1 a a
0 a b
0 a,a a,b
0 a,a a,b,a
1 a,a,b a,b,a
1 a,,b ,b,a
0 a, d,
8 rows selected