我想比較表-1的columnn-A和表-2的B列。都有逗號分隔值。
在我的情況下,如果列B中的所有值都存在列A中,我必須返回TRUE
否則爲false。請指教。例如:比較兩個不同oracle表中的2個逗號分隔列
1.Column A已經A,B,C,DEF列B有A,C,B其應返回TRUE
2.柱1具有VVV,CCC,RR柱2具有CCC,RR, 125應該返回FALSE
3.第1列空,第2列有null,則應該返回TRUE
請幫
我想比較表-1的columnn-A和表-2的B列。都有逗號分隔值。
在我的情況下,如果列B中的所有值都存在列A中,我必須返回TRUE
否則爲false。請指教。例如:比較兩個不同oracle表中的2個逗號分隔列
1.Column A已經A,B,C,DEF列B有A,C,B其應返回TRUE
2.柱1具有VVV,CCC,RR柱2具有CCC,RR, 125應該返回FALSE
3.第1列空,第2列有null,則應該返回TRUE
請幫
希望這個片段幫助。
SELECT DECODE(NULLIF(
(SELECT LISTAGG(x.col_val,',') WITHIN GROUP(
ORDER BY x.col_val)intrsctnVal
FROM
(SELECT SUBSTR(REPLACE(COL2,',',''),LEVEL,1) col_val
FROM
(SELECT 'a,b,c' AS COL2 FROM DUAL
)B
CONNECT BY level <= regexp_count(col2,',')+1
INTERSECT
SELECT SUBSTR(REPLACE(COL1,',',''),LEVEL,1) col_val
FROM
(SELECT 'a,b,c,d' AS COL1 FROM DUAL
)A
CONNECT BY LEVEL <= REGEXP_COUNT(COL1,',')+1
)X
),
(SELECT 'a,b,c' AS COL2 FROM DUAL
)),NULL,'TRUE','FALSE') MATCH
FROM DUAL;
現在做這些值來自兩個表被連接在一起?它是可以做到的,但是很混亂,複雜而且很慢(同一個連接重複多次)。 – MatBailie
我們一直希望這會有所幫助,但一些額外的筆記可能會大大增加其實際幫助的可能性。 – miracle173
非常感謝,很抱歉沒有看到它,我的appologies。 – Arch
最終,我知道了) 這是一個有趣的任務對我來說,只使用SQL解決它:
B N SORTED BOOL
---------- ---------- -------------------------------------------------------------------------------- -----
1 1 [a],[b],[c] true
1 2 [ccc],[rr],[vvv] false
1 3 [] true
1步:聯盟兩個表:
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步:計數分隔符:
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步驟:計算值邊界值
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步驟:產生用於行
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步驟新的查詢:主查詢
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步驟:排序值
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步:重新當然,使用函數好得多,但是,我只是想找到一種只使用SQL的方法。
(2017年6月5日:新增功能)
功能可以是:
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;
/
測試:
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
不要使用「[^,] +」'形式的正則表達式來分析分隔字符串。如果有一個NULL元素,它將失敗。在這裏看到更多的信息:https://stackoverflow.com/a/31464699/2543416 –
這讓我感到驚訝。謝謝,@Gary_W – saphsys
這對我來說也是!我發現生產報告中的一個錯誤報告了錯誤的數據(我們有一個供應商系統超出了我們的控制範圍,其列包含逗號分隔值列表)。現在我正在執行一項任務,告誡人們。不好的部分是,這是在尋找如何解析分隔列表的人的回覆中找到的常見正則表達式。加入我的使命! –
嘛,你嘗試過什麼? – OldProgrammer
當前的表格設計打破了第一種正常形式,每個值應該是原子*(每個值單獨的字段或行,而不是將它們填入單個字符串)*。我強烈建議修復設計。 (這種設計讓世界受到傷害。) – MatBailie
你的例子不僅打破了良好的設計原則,而且打破了三值邏輯的基本規則。 NULL永遠不會等於任何東西,包括NULL。任何與NULL的比較都不會返回TRUE或FALSE,而是返回NULL。基本上你在這裏得到的是通常所說的「製造中的災難」。所有這些關係設計規則,以及所有關於「規範化」和東西的東西?是的 - 這是爲了防止你犯這種錯誤。不要這樣做! (如果這是一次課堂練習,我有權告訴你的老師這是一個非常糟糕的例子,祝你好運)。 –