Oracle / SQL - 从字符串中选择缺少的值

时间:2016-06-07 10:45:28

标签: sql oracle

所以我一直在寻找,但我找不到任何我需要的帮助。

我有这个查询来搜索特定值列表中缺少的内容,但除了查明是否实际缺少某些内容之外,我还需要知道缺少WHICH值:

SELECT t1.*, 
FROM tabl1 t1
WHERE col1 IN ('31' , '32') 
AND NOT (valList LIKE '%;13;%' AND valList LIKE '%;19;%')
OR NOT (valList LIKE '%;15;%');

因此,如果列表包含;13;15;,我需要知道缺少的值是19。

提前致谢! RMGz

2 个答案:

答案 0 :(得分:1)

您的数据格式非常糟糕。您不应该将事物列表(尤其是数字)存储为字符串。

但是如果数据格式不正确,您可以使用case来提供列表:

SELECT t1.*,
       ((CASE WHEN valList NOT LIKE '%;13;%' THEN '13;' ELSE '' END) ||
        (CASE WHEN valList NOT LIKE '%;19;%' THEN '19;' ELSE '' END) ||
        (CASE WHEN valList NOT LIKE '%;15;%' THEN '15;' ELSE '' END)
       ) as MissingIds
FROM tabl1 t1
WHERE col1 IN ('31' , '32') AND
      NOT (valList LIKE '%;13;%' AND valList LIKE '%;19;%') OR
      NOT (valList LIKE '%;15;%');

您甚至可以使用子查询,因此您不必重复逻辑:

SELECT t1.*
FROM (SELECT t1.*,
             ((CASE WHEN valList NOT LIKE '%;13;%' THEN '13;' ELSE '' END) ||
              (CASE WHEN valList NOT LIKE '%;19;%' THEN '19;' ELSE '' END) ||
              (CASE WHEN valList NOT LIKE '%;15;%' THEN '15;' ELSE '' END)
             ) as MissingIds
      FROM tabl1 t1
      WHERE col1 IN ('31' , '32')
     ) t1
WHERE MIssingIds IS NOT NOT NULL

答案 1 :(得分:0)

您可以使用Oracle的集合:

Oracle安装程序

用于存储多个字符串的集合:

CREATE TYPE VARCHAR2_TABLE AS TABLE OF VARCHAR2(4000);
/

将列表拆分为字符串集合的辅助函数:

CREATE OR REPLACE FUNCTION split_String(
  i_str    IN  VARCHAR2,
  i_delim  IN  VARCHAR2 DEFAULT ','
) RETURN VARCHAR2_TABLE DETERMINISTIC
AS
  p_result       VARCHAR2_TABLE := VARCHAR2_TABLE();
  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;
/

<强>查询

SELECT *
FROM   (
  SELECT t.*,
         varchar2_table( '15', '13', '19' )
           MULTISET EXCEPT split_string( TRIM( BOTH ';' FROM valList ), ';' )
           AS missing_values
  FROM   tabl1 t
)
WHERE  missing_values IS NOT EMPTY;

然后,您可以通过将尽可能多(或几个)的值传递到集合中来修改查询(甚至可以pass a collection as a bind value),并且您不必添加许多CASE语句。

相关问题