Oracle检查另一个表中是否存在多个字符串中的任何一个

时间:2018-03-14 03:51:24

标签: sql oracle

我是Oracle的新手。我有一个要求,我需要从注释字段中获取所有错误代码,然后在另一个表中检查它以查看代码类型。根据代码类型,我必须优先选择特定类型,然后显示该错误代码并键入csv以及其他列。下面列中的数据如何

表1:COMMENTS_TABLE

  id   | comments
  1    | Manually added (BPM001). Currency code does not exists(TECH23).  
  2    | Invalid counterparty (EXC001). Manually added (BPM002)

表2:ERROR_CODES

  id    | error_code  | error_type  
  1     | BPM001      | MAN  
  2     | EXC001      | EXC         
  3     | EXC002      | EXC
  4     | BPM002      | MAN 

我可以使用REGEX_SUBSTR获取所有错误代码,但不知道如何使用其他表格检查它,具体取决于类型只显示一个。例如。如果类型只是MAN,那么应该在select子句中返回错误代码。

2 个答案:

答案 0 :(得分:1)

我建议您定义error_codes的层次结构 在FIRST函数内搜索最佳匹配。

SQL Fiddle

查询1

 SELECT c.id,
         MAX (
            ERROR_CODE)
         KEEP (DENSE_RANK FIRST
               ORDER BY CASE ERROR_TYPE WHEN 'MAN' THEN 1 WHEN 'EXC' THEN 2 END)
            AS ERROR_CODE,
         MAX (
            ERROR_TYPE)
         KEEP (DENSE_RANK FIRST
               ORDER BY CASE ERROR_TYPE WHEN 'MAN' THEN 1 WHEN 'EXC' THEN 2 END)
            AS ERROR_TYPE
    FROM ERROR_CODES e
         JOIN COMMENTS_TABLE c ON c.COMMENTS LIKE '%' || e.ERROR_CODE || '%'
GROUP BY c.id

<强> Results

| ID | ERROR_CODE | ERROR_TYPE |
|----|------------|------------|
|  1 |     BPM001 |        MAN |
|  2 |     BPM002 |        MAN |

编辑:您在评论中说过

  

这是helpul,但我在select子句中有多个字段并添加   在分组中可能是一个问题

一个选项可能是使用WITH子句来定义此结果集,然后与其他列连接。

with res as
(
  select ...
         --query1
)
select t.other_columns, r.id, r.error_code ... 
   from other_table join res on ...

您也可以选择使用row_number()(这实际上是我的原始答案。但我将其更改为KEEP .. DENSE_RANK,因为它效率很高。

SELECT * FROM
( SELECT c.id
    ,ERROR_CODE
    ,ERROR_TYPE
    --Other columns,
    ,row_number() OVER (
        PARTITION BY c.id ORDER BY CASE error_type
                WHEN 'MAN'
                    THEN 1
                WHEN 'EXC'
                    THEN 2
                ELSE 3
                END
        ) AS rn
FROM ERROR_CODES e
INNER JOIN COMMENTS_TABLE c 
ON c.COMMENTS LIKE '%' || e.ERROR_CODE || '%'
 ) WHERE rn = 1;

Fiddle

答案 1 :(得分:0)

您可以使用分析函数对记录进行排序,确定优先级并对其进行过滤。

with comments as(
    select 1 as id
          ,'Manually added (BPM001). Currency code does not exists(TECH23).' as comments 
      from dual union all
    select 2 as id
          ,'Invalid counterparty (EXC001). Manually added (BPM002)'          as comments 
      from dual
)
,error_codes as(
    select 1 as id, 'BPM001' as error_code, 'MAN' as error_type from dual union all 
    select 2 as id, 'EXC001' as error_code, 'EXC' as error_type from dual union all        
    select 3 as id, 'EXC002' as error_code, 'EXC' as error_type from dual union all
    select 4 as id, 'BPM002' as error_code, 'MAN' as error_type from dual
)
-- Everything above this line is not part of the query. Just for generating test data
select * 
  from (select c.id as comment_id
              ,c.comments
              ,e.error_code
              ,row_number() over(
                partition by c.id                              -- For each comment
                    order by case error_type when 'MAN' then 1 -- First prio
                                             when 'EXC' then 2 -- Second prio
                                                        else 3 -- Everything else
                              end) as rn
           from comments    c
           join error_codes e on(
                e.error_code = regexp_substr(c.comments, e.error_code)
           )
        )
  where rn = 1 -- Pick the highest priority code
 /

如果你可以为你的错误代码(甚至是error_type)添加一个优先级列,你可以跳过大小写/当顺序中的逻辑时,只需用优先级列替换它。