簡體   English   中英

我如何從字符串中提取 substring 並在 Oracle SQL 中創建一個新的數字列

[英]How would I extract a substring from a string and create a new numeric column in Oracle SQL

我有一列 (DFI6),其中的值看起來像這樣,我有數百萬個。 我試圖用 COD (COD1,COD2....COD5) 值創建一個新的 NUMERIC 列。

表格的圖像這是它應該看起來的樣子,我有第一列,我正在嘗試創建 5 個新列

現在我正處於開始階段,我正在嘗試創建單獨的查詢並對其進行測試,而不是一個大的嵌套查詢。

有時 COD5 的值是字面上的“無”。 我查詢提取 COD5

 select DFI6, (case when DFI6 like '%COD5%' THEN (case when REGEXP_LIKE(SUBSTR(SUBSTR(DFI6, INSTR(DFI6,'COD5=')),6),'[az]') then '-1' else (nvl(SUBSTR(SUBSTR(DFI6, INSTR(DFI6,'COD5=')),6),'-1')) end) else '-1' end)+0 --note: I added zero to turn the column into numeric as COD5 from myTable where updated_date>sysdate-300 and DFI6 is not null

提取 COD4 的查詢是:

 select DFI6, (case when DFI6 like '%COD4%' THEN (case when REGEXP_LIKE(SUBSTR(SUBSTR(DFI6, INSTR(DFI6,'COD4=')),6),'[az]') then '-1' else SUBSTR(SUBSTR(DFI6, INSTR(DFI6, 'COD3'), INSTR(DFI6, '|COD4') - INSTR(DFI6, 'COD3')),6) end) else '-1' end)+0 --note: I added zero to turn the column into numeric as COD4 from myTable where updated_date>sysdate-30 and DFI6 is not null

問題:

  • 一些 DEF6 列不包含特定的 COD,如果不包含,則 -1 應該在相關的 COD 子列中。
  • 一些 COD 值可以是 null,如果它們是 -1,則應該在相關的 COD 列中。
  • 當我在 case 語句的末尾添加 0 時,列是數字的,但我無法獲取所有行。 但是,當我不加零時,該列是非數字的,但會獲取所有行。 基本上我丟失了 600-900k 行。
  • 我試圖將整個 case 語句包裝到 to_number 中,但沒有成功。

我正在使用 SQL navigator6.2.1 oracle DB 版本 [19.16.0.0.0],一些新功能不適用於我的版本。 我是 SQL 的新手,非常感謝任何幫助。 謝謝

試試這個——只使用 CASE 表達式和 SubStr() function:

WITH      -- Sample data
    tbl  AS
        (
            Select 'COD1=01YTEFG|COD2=22|COD3=33|COD4=21|COD5=22' "DFI6" From Dual Union All
            Select 'COD1=02YTEFG|COD2=25|COD3=37|COD4=27|COD5=28' "DFI6" From Dual Union All
            Select 'COD1=01YTEFG|COD2=22|COD3=33|COD4=21|COD5=22' "DFI6" From Dual Union All
            Select 'COD1=02YTEFG|COD2=25|COD3=37|COD4=27' "DFI6" From Dual Union All        -- NO COD5
            Select 'COD1=02YTEFG|COD2=253|COD3=37|COD4=27' "DFI6" From Dual Union All        -- NO COD5  AND   COD2 HAS THREE NUMBERS
            Select 'COD1=None|COD2=22|COD3=33|COD4=21|COD5=22' "DFI6" From Dual Union All     -- COD1 = None
            Select 'COD1=02YTEFG|COD5=28' "DFI6" From Dual Union All                          -- NO CODES 2, 3 AND 4
            Select 'COD1=01YTEFG|COD2=22|COD3=33|COD4=21|COD5=22' "DFI6" From Dual Union All
            Select 'COD1=02YTEFG|COD2=25|COD3=37|COD4=27|COD5=Nothing' "DFI6" From Dual 
        )
--
--  Main SQL
SELECT
    DFI6,
    CASE 
        WHEN  INSTR(DFI6, 'COD1=') = 0 OR                                               -- element is not here OR
              INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD1=') + 5, 1)) = 0        -- first char after 'COD1=' is not numeric
        THEN -1   
        --
        WHEN  INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD1=') + 7, 1)) > 0 AND    -- third and
              INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD1=') + 6, 1)) > 0 AND    -- second and
              INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD1=') + 5, 1)) > 0        -- first char after 'COD1=' are all numerics 
        THEN To_Number(SubStr(DFI6, InStr(DFI6, 'COD1=') + 5, 3))                   -- take all three 
        --
        WHEN  INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD1=') + 6, 1)) > 0 AND    -- second and
              INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD1=') + 5, 1)) > 0        -- first char after 'COD1=' are both numerics
        THEN To_Number(SubStr(DFI6, InStr(DFI6, 'COD1=') + 5, 2))                   -- take them both 
        --
        WHEN  INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD1=') + 5, 1)) > 0        -- just 1 numeric char after 'COD1='
        THEN To_Number(SubStr(DFI6, InStr(DFI6, 'COD1=') + 5, 1))                   -- take it
    ELSE -1 END "COD1",                                                     -- ELSE -1
    --          ---------------------------------------------
    CASE 
       WHEN  INSTR(DFI6, 'COD2=') = 0 OR 
              INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD2=') + 5, 1)) = 0
        THEN -1   
        --
        WHEN  INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD2=') + 7, 1)) > 0 AND 
              INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD2=') + 6, 1)) > 0 AND 
              INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD2=') + 5, 1)) > 0
        THEN To_Number(SubStr(DFI6, InStr(DFI6, 'COD2=') + 5, 3))
        --
        WHEN  INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD2=') + 6, 1)) > 0 AND 
              INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD2=') + 5, 1)) > 0 
        THEN To_Number(SubStr(DFI6, InStr(DFI6, 'COD2=') + 5, 2))
        --
        WHEN  INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD2=') + 5, 1)) > 0 
        THEN To_Number(SubStr(DFI6, InStr(DFI6, 'COD2=') + 5, 1))
    ELSE -1 END "COD2",
    --          ---------------------------------------------
    CASE 
       WHEN  INSTR(DFI6, 'COD3=') = 0 OR 
              INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD3=') + 5, 1)) = 0
        THEN -1   
        --
        WHEN  INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD3=') + 7, 1)) > 0 AND 
              INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD3=') + 6, 1)) > 0 AND 
              INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD3=') + 5, 1)) > 0
        THEN To_Number(SubStr(DFI6, InStr(DFI6, 'COD3=') + 5, 3))
        --
        WHEN  INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD3=') + 6, 1)) > 0 AND 
              INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD3=') + 5, 1)) > 0 
        THEN To_Number(SubStr(DFI6, InStr(DFI6, 'COD3=') + 5, 2))
        --
        WHEN  INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD3=') + 5, 1)) > 0 
        THEN To_Number(SubStr(DFI6, InStr(DFI6, 'COD3=') + 5, 1))
    ELSE -1 END "COD3",
    --          ---------------------------------------------
    CASE 
       WHEN  INSTR(DFI6, 'COD4=') = 0 OR 
              INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD4=') + 5, 1)) = 0
        THEN -1   
        --
        WHEN  INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD4=') + 7, 1)) > 0 AND 
              INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD4=') + 6, 1)) > 0 AND 
              INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD4=') + 5, 1)) > 0
        THEN To_Number(SubStr(DFI6, InStr(DFI6, 'COD4=') + 5, 3))
        --
        WHEN  INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD4=') + 6, 1)) > 0 AND 
              INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD4=') + 5, 1)) > 0 
        THEN To_Number(SubStr(DFI6, InStr(DFI6, 'COD4=') + 5, 2))
        --
        WHEN  INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD4=') + 5, 1)) > 0 
        THEN To_Number(SubStr(DFI6, InStr(DFI6, 'COD4=') + 5, 1))
    ELSE -1 END "COD4",
    --          ---------------------------------------------
    CASE 
       WHEN  INSTR(DFI6, 'COD5=') = 0 OR 
              INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD5=') + 5, 1)) = 0
        THEN -1   
        --
        WHEN  INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD5=') + 7, 1)) > 0 AND 
              INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD5=') + 6, 1)) > 0 AND 
              INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD5=') + 5, 1)) > 0
        THEN To_Number(SubStr(DFI6, InStr(DFI6, 'COD5=') + 5, 3))
        --
        WHEN  INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD5=') + 6, 1)) > 0 AND 
              INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD5=') + 5, 1)) > 0 
        THEN To_Number(SubStr(DFI6, InStr(DFI6, 'COD5=') + 5, 2))
        --
        WHEN  INSTR('0123456789', SubStr(DFI6, InStr(DFI6, 'COD5=') + 5, 1)) > 0 
        THEN To_Number(SubStr(DFI6, InStr(DFI6, 'COD5=') + 5, 1))
    ELSE -1 END "COD5"
FROM tbl
--
/*    R e s u l t :
DFI6                                                    COD1       COD2       COD3       COD4       COD5
------------------------------------------------- ---------- ---------- ---------- ---------- ----------
COD1=01YTEFG|COD2=22|COD3=33|COD4=21|COD5=22               1         22         33         21         22 
COD1=02YTEFG|COD2=25|COD3=37|COD4=27|COD5=28               2         25         37         27         28 
COD1=01YTEFG|COD2=22|COD3=33|COD4=21|COD5=22               1         22         33         21         22 
COD1=02YTEFG|COD2=25|COD3=37|COD4=27                       2         25         37         27         -1 
COD1=02YTEFG|COD2=253|COD3=37|COD4=27                      2        253         37         27         -1 
COD1=None|COD2=22|COD3=33|COD4=21|COD5=22                 -1         22         33         21         22 
COD1=02YTEFG|COD5=28                                       2         -1         -1         -1         28 
COD1=01YTEFG|COD2=22|COD3=33|COD4=21|COD5=22               1         22         33         21         22 
COD1=02YTEFG|COD2=25|COD3=37|COD4=27|COD5=Nothing          2         25         37         27         -1
*/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM