Like 运算符来比较两个不同表中的两列

Like operator to compare two columns from two different table

提问人:NEWBIE 提问时间:8/24/2022 最后编辑:MT0NEWBIE 更新时间:8/25/2022 访问量:87

问:

如何从第一个表 (Table_A) 中提取记录,该表具有嵌入的 CODE 值的 Attr 列,与第二个表(Table_B:CODE 和 DESCR 列)相比,这些值至少包含一个不常见的 CODE 值,以便我得到table_C作为结果? 这是我到目前为止所拥有的:

Select * From Table_A
Where Attr like '%CODE%' AND
    not exist (select * from Table_B
               where Table_A.Attr LIKE '%'||Table_B.CODE||'%')

表A

编号 阿特
1 代码 = A111
2 代码 = 'A111, B222, C333, D444'
3 代码 = 'D444', 'E555', 'F666'
4 代码 = 'G777', 'B222'
5 项目 = 'AFRD' 和代码 = 'C333'
6 项目 = BYNM

table_B

法典 DESCR的
答111 DJIEFLJFE
D444型 qrrascjg
E555型 WPOFLER公司
F666型 NFOSMWFA
G777型 洛斯克

table_C

编号 阿特
2 代码 = 'A111, B222, C333, D444'
4 代码 = 'G777', 'B222'
5 项目 = 'AFRD' 和代码 = 'C333'
Oracle 类 SQL

评论

0赞 Olivier Jacot-Descombes 8/24/2022
您的结果表是否正确?只有记录 ID=5 不包含来自 Table_B 的代码。
0赞 NEWBIE 8/24/2022
ID= 2 包含 B222,C333 ID = 4 包含不在 table_b 中的 B222
0赞 Olivier Jacot-Descombes 8/24/2022
这对于 SQL LIKE 命令是不可行的。该列必须拆分为单个代码,并且必须对每个代码应用测试。@AlexPoole显示了一种可能的 SQL 方法。中的信息更适合在前端进行处理。AttrAttr

答:

0赞 Olivier Jacot-Descombes 8/24/2022 #1

您必须提供别名,以便可以在嵌套选择中引用它:Table_A

SELECT *
FROM
    Table_A A
WHERE
    Attr LIKE '%CODE%' AND
    NOT EXISTS
    (
        SELECT *
        FROM Table_B
        WHERE A.Attr LIKE '%'||Table_B.CODE||'%'
    )

此外,关键字不是 .EXISTSEXIST

SQL 无法解析复杂的任意表达式,例如 and 区分代码和项目。但是,如果项目 ID 始终与代码不同,则这不是问题。ITEM = 'AFRD' AND CODE = 'C333'C333AFRD

请参见:http://sqlfiddle.com/#!4/995f23/1/0

评论

0赞 NEWBIE 8/24/2022
此查询仅拉取记录 ID = 5,我也需要它拉取 2 和 4。我正在寻找包含表 B 中没有的代码的所有记录。
1赞 Alex Poole 8/24/2022 #2

只要代码始终跟在项目后面,就可以使用以下命令提取代码列表:

regexp_substr(attr, '.*(CODE = ?)(.*?)', 1, 1, null, 2

并删除空格和引号

translate(regexp_substr(attr, '.*(CODE = ?)(.*?)', 1, 1, null, 2), q'^x' ^', 'x')

获取要查找的简单逗号分隔值列表,例如 ;然后将其拆分为单独的元素,例如使用递归子查询分解;并找到其他表中不存在的任何内容。G777,B222

这很混乱,但是:

with cte (id, attr, codes) as (
  select id, attr,
    translate(
      regexp_substr(attr, '.*(CODE = ?)(.*?)', 1, 1, null, 2),
      q'^x' ^', 'x'
    )
  from table_a
),
rcte (id, attr, codes, pos, code) as (
  select id, attr, codes, 1, regexp_substr(codes, '(.*?)(,|$)', 1, 1, null, 1)
  from cte
  where codes is not null
  union all
  select id, attr, codes, pos + 1, regexp_substr(codes, '(.*?)(,|$)', 1, pos + 1, null, 1)
  from rcte
  where regexp_substr(codes, '(.*?)(,|$)', 1, pos + 1, null, 1) is not null
)
select distinct r.id, r.attr
from rcte r
where not exists (
  select null
  from table_b b
  where b.code = r.code
)

ID ATTR
2 CODE = 'A111, B222, C333, D444'
4 CODE = 'G777', 'B222'
5 ITEM = 'AFRD' AND CODE = 'C333'

db<>fiddle

The gets the simple CSV values; splits those up to individual components (and assumes there will be no empty elements), and then those individual values are checked with . Which gives duplicate id/attr pairs, so removes the duplicates; but you can also see which code(s) didn't exist if you want, by not applying distinct, and potentially using to still get a single result per ID.cterctenot existsdistinctlistagg

It's painful, but that's what happens with data stored like this...

评论

1赞 Olivier Jacot-Descombes 8/24/2022
Yes, this data is not normalized. The codes should be stored in a separate table.
0赞 Barbaros Özhan 8/24/2022 #3

You can use an outer join among Table_A and Table_B in order to obtain unmatched codes after converting comma separated codes to the newly generated rows per each individual code through use of regular expression functions along with a hierarchical query such as

WITH a0 AS
(
 SELECT id, CASE WHEN INSTR(attr, 'CODE')>0 THEN
                      REGEXP_REPLACE(attr,'(.*CODE =)+') 
                  END AS codes
   FROM Table_A
), a AS
(   
 SELECT id, TRIM(BOTH CHR(39) FROM TRIM(REGEXP_SUBSTR(codes,'[^,]+',1,level)) ) AS codes
   FROM a0
  WHERE codes IS NOT NULL 
CONNECT BY LEVEL <= REGEXP_COUNT(codes, ',') + 1
    AND PRIOR SYS_GUID() IS NOT NULL
    AND PRIOR id = id   
)
SELECT a.*
  FROM Table_A a
  JOIN (SELECT DISTINCT id 
          FROM a 
          LEFT JOIN Table_B 
            ON code = codes 
         WHERE code IS NULL) b
     ON a.id = b.id 

Demo