2017-06-06 57 views
0

我正在查找Oracle SQL查詢以查找特定模式,並用另一個表中的值替換它們。找到收集數據的方法,並用另一個表中的值替換

場景:

表1:

No  column1 
----------------------------------------- 
12345 user:12345;group:56789;group:6785;... 

注:字段1可以是具有一個或多個圖案

表2:

Id  name  type 
---------------------- 
12345 admin  user 
56789 testgroup group 

結果必須是相同的

No  column1 
----------------------------------- 
12345  user: admin;group:testgroup 
+0

爲什麼PLSQL?不是普通的SQL查詢很好嗎?另外,你到目前爲止嘗試過什麼? – Aleksej

+0

我的數據庫是oracle,我可以對它們進行操作 – user3728800

+1

PLSQL是SQL的Oracle過程擴展。如果您需要爲Oracle工作的SQL查詢,您最好標記Oracle和SQL,而不是PLSQL。另外,請發佈您迄今爲止嘗試/搜索的內容 – Aleksej

回答

0

邏輯:

  • 第一分割串聯的字符串使用connect by子句和正則表達式的各個行。
  • 將新創建的表(split_tab)與Table2(tab2)加入。
  • 使用listagg函數來連接列中的數據。

查詢:

WITH tab1 AS 
    (SELECT '12345' NO 
      ,'user:12345;group:56789;group:6785;' column1 
     FROM DUAL) 
    ,tab2 AS 
    (SELECT 12345 id 
      ,'admin' name 
      ,'user' TYPE 
     FROM DUAL 
     UNION 
     SELECT 56789 id 
      ,'testgroup' name 
      ,'group' TYPE 
     FROM DUAL) 
SELECT no 
     ,listagg(category||':'||name,';') WITHIN GROUP (ORDER BY tab2.id) column1 
    FROM (SELECT NO 
        ,REGEXP_SUBSTR(column1, '(\d+)', 1, LEVEL) id 
        ,REGEXP_SUBSTR(column1, '([a-z]+)', 1, LEVEL) CATEGORY 
       FROM tab1 
     CONNECT BY LEVEL <= regexp_count(column1, '\d+')) split_tab 
     ,tab2 
WHERE split_tab.id = tab2.id 
GROUP BY no 

輸出:

No  Column1 
12345 user:admin;group:testgroup 
+0

查詢未優化,CPU增加到100%,並且在運行後oracle無法響應另一個查詢 – user3728800

+0

@ user3728800我已經測試過它並且工作正常。 –

+0

我擁有擁抱數據,並根據樣本 – user3728800

0
with t1 (no, col) as 
(
    -- start of test data 
    select 1, 'user:12345;group:56789;group:6785;' from dual union all 
    select 2, 'user:12345;group:56789;group:6785;' from dual 
    -- end of test data 
) 
    -- the lookup table which has the substitute strings 
    -- nid : concatenation of name and id as in table t1 which requires the lookup 
    -- tname : required substitute for each nid 
, t2 (id, name, type, nid, tname) as 
(

    select t.*, type || ':' || id, type || ':' || name from 
    (
    select 12345 id, 'admin' name,  'user' type from dual union all 
    select 56789, 'testgroup', 'group' from dual 
) t 
) 
--select * from t2; 
-- cte table calculates the indexes for the substrings (eg, user:12345) 
-- no : sequence no in t1 
-- col : the input string in t1 
-- si : starting index of each substring in the 'col' input string that needs attention later 
-- ei : ending index of each substring in the 'col' input string 
-- idx : the order of substring to put them together later 
,cte (no, col, si, ei, idx) as 
(
    select no, col, 1, case when instr(col,';') = 0 then length(col)+1 else instr(col,';') end, 1 from t1 union all 
    select no, col, ei+1, case when instr(col,';', ei+1) = 0 then length(col)+1 else instr(col,';', ei+1) end, idx+1 from cte where ei + 1 <= length(col) 
) 
,coll(no, col, sstr, idx, newstr) as 
(
    select 
    a.no, a.col, a.sstr, a.idx, 
    -- when a substitute is not found in t2, use the same input substring (eg. group:6785) 
    case when t2.tname is null then a.sstr else t2.tname end 
    from 
    (select cte.*, substr(col, si, ei-si) as sstr from cte) a 
    -- we don't want to miss if there is no substitute available in t2 for a substring 
    left outer join 
    t2 
    on (a.sstr = t2.nid) 
) 
select no, col, listagg(newstr, ';') within group (order by no, col, idx) from coll 
group by no, col; 
相關問題