2017-02-15 56 views
-2

我所說的互聯網服務和我得到的代碼列表變量不同名單查詢表:A,B,C,d,E,F等與使用類似

在我的問題,我得到A,B, C.

有一個表格,您可以使用上面的代碼創建集合,並且可以爲每個集合添加特定的消息,以便最終用戶可以理解代碼。 例如A表示「ok」,B表示「您可以登錄」 因此,對於集合A,B,消息可以是「您可以登錄」。 代碼集保存在一列(代碼)中。

Select setid, codes, messagedescr from table1 where setid = (select max(setid) from table1 
         And codes Like '%A%' 
         And codes Like '%B%' 
         And codes Like '%C%'); 

這個查詢找到了行,但它是錯的,列「代碼」包含以下代碼:A,B,C,d

在我的問題,我使用下面的查詢查詢表。

例如:

setid codes  messagedescr 
1  A, B, C, D You can login 
2  B, C, D  You can login for one day 
3  A, C, E  You can login but update your profile 
4  B, C, E, F You cannot login 

我不知道從Web服務代碼的順序,我做的代碼不如何保存在表,所以我不得不作出一些無秩序, 這個爲什麼我使用了喜歡。 有25個代碼:A,B,C等

我該如何修復查詢,以便找到正確的信息?

謝謝!

更新: 非常感謝大家的回答,特別是有更多詳細答案,如創建表格等額外工作。 該表可能有10-20行。 一種情況是爲代碼創建另一個表並將其與設置ID一起加入。或者另一種情況是計算服務中代碼的長度,並查看它們是否與表中的長度相匹配。

+1

能否請您發佈一些示例數據和預期的結果? (格式文本,請) – Aleksej

+0

@Tsiftelis Thanasis,如果您發佈A,B,C表示whict消息,你想dispaly.ie A的消息或B的消息或C的消息,什麼是你優先級。 – Mansoor

+1

這是DB設計不佳的後果。不要將多個代碼存儲在單個列中;使用單獨的表格。 – dasblinkenlight

回答

1

如果我明白你的需要,這可能是一種方法。

說你有一個像這樣的表:

create table yourTable(setid, codes, messagedescr) as ( 
    select 1,  'A, B, C, D', 'You can login' from dual union all 
    select 2,  'B, C, D' , 'You can login for one day' from dual union all 
    select 3,  'A, C, E' , 'You can login but update your profile' from dual union all 
    select 4,  'B, C, E, F', 'You cannot login' from dual 
). 

這可能是一個辦法:

with inputData(codes) as (
    select listagg(trim (regexp_substr(input_codes, '[^,]+', 1, level))) within group (order by trim (regexp_substr(input_codes, '[^,]+', 1, level))) 
    from (select 'A, D, C, B' as input_codes from dual) /* the input string */ 
    CONNECT BY instr(input_codes, ',', 1, level - 1) > 0 
)  
select * 
from inputData 
    inner join (
       select listagg(trim (regexp_substr(codes, '[^,]+', 1, level))) 
         within group (order by trim (regexp_substr(codes, '[^,]+', 1, level))) as codes, 
         messagedescr 
       from yourTable 
       CONNECT BY instr(codes, ',', 1, level - 1) > 0 
        and prior setId = setId 
        and prior sys_guid() is not null 
       group by setId, messagedescr 
       ) 
     using (codes) 

這裏的想法是分裂在許多行你輸入的字符串,然後聚集所產生的按字母順序排列,然後對錶中的值應用相同的順序,然後檢查排序的字符串是否相等。

這部分是用於分割,順序和聚合的輸入值,以使得結果是有序字符串:

select listagg(trim (regexp_substr(input_codes, '[^,]+', 1, level))) within group (order by trim (regexp_substr(input_codes, '[^,]+', 1, level))) 
    from (select 'A, D, C, B' as input_codes from dual) /* the input string */ 
    CONNECT BY instr(input_codes, ',', 1, level - 1) > 0 

給出:

ABCD 

這部分是用來做同你的桌子上:

select listagg(trim (regexp_substr(codes, '[^,]+', 1, level))) 
     within group (order by trim (regexp_substr(codes, '[^,]+', 1, level))) as codes, 
     messagedescr 
from yourTable 
CONNECT BY instr(codes, ',', 1, level - 1) > 0 
    and prior setId = setId 
    and prior sys_guid() is not null 
group by setId, messagedescr 

給出:

CODES  MESSAGEDESCR 
---------- ------------------------------------- 
ABCD  You can login 
BCD  You can login for one day 
ACE  You can login but update your profile 
BCEF  You cannot login 

這些部分結果之間的連接非常簡單,只需檢查您的表中是否存在與(有序)輸入字符串對應的值(有序)。

1

甲骨文設置

開始用一個簡單的功能split a delimited string到一個集合:

CREATE OR REPLACE TYPE stringlist AS TABLE OF VARCHAR2(20) 
/

CREATE OR REPLACE FUNCTION split_String(
    i_str IN VARCHAR2, 
    i_delim IN VARCHAR2 DEFAULT ',' 
) RETURN stringlist DETERMINISTIC 
AS 
    p_result  stringlist := stringlist(); 
    p_start  NUMBER(5) := 1; 
    p_end   NUMBER(5); 
    c_len CONSTANT NUMBER(5) := LENGTH(i_str); 
    c_ld CONSTANT NUMBER(5) := LENGTH(i_delim); 
BEGIN 
    IF c_len > 0 THEN 
    p_end := INSTR(i_str, i_delim, p_start); 
    WHILE p_end > 0 LOOP 
     p_result.EXTEND; 
     p_result(p_result.COUNT) := SUBSTR(i_str, p_start, p_end - p_start); 
     p_start := p_end + c_ld; 
     p_end := INSTR(i_str, i_delim, p_start); 
    END LOOP; 
    IF p_start <= c_len + 1 THEN 
     p_result.EXTEND; 
     p_result(p_result.COUNT) := SUBSTR(i_str, p_start, c_len - p_start + 1); 
    END IF; 
    END IF; 
    RETURN p_result; 
END; 
/

和一些樣本數據:

CREATE TABLE your_table(setid, codes, messagedescr) 
    SELECT 1, 'A,B,C,D', 'You can login' FROM DUAL UNION ALL 
    SELECT 2, 'B,C,D', 'You can login for one day' FROM DUAL UNION ALL 
    SELECT 3, 'A,C,E', 'You can login but update your profile' FROM DUAL UNION ALL 
    SELECT 4, 'B,C,E,F', 'You cannot login' FROM DUAL; 

然後你可以做(​​通過你的輸入C,A,B - 以任何順序 - 爲綁定參數:your_code):

SELECT * 
FROM (
    SELECT * 
    FROM your_table 
    WHERE split_string(codes) SUBMULTISET OF split_String(:your_code) 
    ORDER BY setid DESC 
) 
WHERE ROWNUM = 1; 

並且它將輸出具有最高匹配代碼集合的行。

注意:上述示例假定您需要將表中的所有代碼與輸入字符串中的代碼進行匹配。如果你只需要匹配至少一個,那麼你可以使用:

WHERE split_string(codes) MULTISET INTERSECT split_String(:your_code) IS NOT EMPTY