我打电话给网络服务,我得到一个代码列表: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
我不知道网络服务中代码的顺序,我不知道代码是如何保存在表格中的,所以我不得不做一些没有订单的东西,这就是我使用Likes的原因。 共有25个代码:A,B,C等
如何修复查询以便找到正确的消息?
谢谢!
更新 谢谢大家的答案,特别是那些有额外工作的更详细的答案,比如创建表格。 该表可能有10-20行。 一种情况是为代码创建另一个表并将其与set id连接。或者另一种情况是计算服务中代码的长度,看它们是否与表中的长度匹配。
答案 0 :(得分: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 :(得分:1)
Oracle安装程序:
从一个简单的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