2017-07-03 28 views
-1

的範圍列得到的結果我有一個像(1,2,20-25,222-256)甲骨文:如何從表中包含字符串

用含值varchar2列的表現在我必須篩選基於以下搜索條件的記錄(24,210,300,250)

樣本記錄

Id | RangeOfString 
--------------------------- 
1 | 20-25, 101, 222-256, 1001-1045, 1046, 1047, 1048 
2 | 1, 2, 3, 2100-2300 
3 | 56-89, 186-326, 548, 601, 875 

預期結果

Id | RangeOfString 
--------------------------- 
1 | 20-25, 101, 222-256, 1001-1045, 1046, 1047, 1048 
3 | 56-89, 186-326, 548, 601, 875 
+1

爲什麼不正常化您的數據?然後您的查詢將非常容易 –

+0

@a_horse_with_no_name,感謝您的快速回復,我只讀了表格的訪問權限。 –

+0

這太可怕了,您需要將逗號分隔值拆分爲行,然後將2個路徑,單個值轉換爲數字並進行比較,或者將範圍拆分爲低/高值,然後使用之間進行轉換和比較。可怕。 (哦,希望像轉換爲數字時沒有錯誤發生)。 –

回答

1

您可以編寫一個函數返回一個集合:

甲骨文設置

CREATE TYPE intlist IS TABLE OF INTEGER; 
/

CREATE PROCEDURE splitGroupedList(
    p_grouped IN VARCHAR2, 
    p_delimiter IN VARCHAR2 DEFAULT ',', 
    p_separator IN VARCHAR2 DEFAULT '-' 
) RETURN intlist DETERMINISTIC 
AS 
    v_start PLS_INTEGER := 1; 
    v_end  PLS_INTEGER; 
    v_sep  PLS_INTEGER; 
    v_range VARCHAR2(4000); 
    v_lower INTEGER; 
    v_upper INTEGER; 
    v_numbers intlist := intlist(); 
    c_del_len CONSTANT PLS_INTEGER := LENGTH(p_delimiter); 
    c_sep_len CONSTANT PLS_INTEGER := LENGTH(p_separator); 
BEGIN 
    IF p_grouped IS NULL THEN 
    RETURN v_numbers; 
    END IF; 
    LOOP 
    EXIT WHEN v_start := 0; 
    v_end := INSTR(p_grouped, p_delimiter, v_start); 
    IF v_end = 0 THEN 
     v_range := SUBSTR(p_grouped, v_start); 
     v_start := 0; 
    ELSE 
     v_range := SUBSTR(p_grouped, v_start, v_end - v_start); 
     v_start := v_end + c_del_len; 
    END IF; 
    IF v_range IS NULL THEN 
     CONTINUE; 
    END IF; 
    v_sep := INSTR(v_range, p_separator); 
    IF v_sep = 0 THEN 
     v_lower := TO_NUMBER(v_range); 
     v_upper := v_lower; 
    ELSE 
     v_lower := TO_NUMBER(SUBSTR(v_range, 1, v_sep - 1)); 
     v_upper := TO_NUMBER(SUBSTR(v_range, v_sep + c_sep_len)); 
    END IF; 
    FOR i IN v_lower .. v_upper LOOP 
     v_numbers.EXTEND; 
     v_numbers(v_numbers.COUNT) := i; 
    END LOOP; 
    END LOOP; 
    RETURN v_numbers; 
END; 
/

查詢

WITH your_data (Id, RangeOfString) AS (
    SELECT 1, '20-25,101,222-256,1001-1045,1046,1047,1048' FROM DUAL UNION ALL 
    SELECT 2, '1,2,3,2100-2300' FROM DUAL UNION ALL 
    SELECT 3, '56-89,186-326,548,601,875' FROM DUAL 
) 
SELECT * 
FROM your_data 
WHERE intlist(24,210,300,250) MULTISET INTERSECT splitGroupedList(RangeOfString) IS NOT EMPTY; 

輸出

ID RANGEOFSTRING 
-- ------------------------------------------ 
1 20-25,101,222-256,1001-1045,1046,1047,1048 
3 56-89,186-326,548,601,875 
+0

你讓我的一天:)解決方案就像一個魅力。感謝您的時間和精力。 –