2017-02-15 39 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