替换 select 结果中所有出现的子查询

Replace all occurrences of subquery in select result

正在从 MySQL 中的 Sparx EA 数据库导出数据。

数据库包含有注释的对象

select o.Note from t_object o

结果可能是

Note
Contains reference to term1 and term2
Another note that mentions term1 only
A note that doesn't mention any terms

还有个词汇表可以这样查询

select g.TERM 
  from t_glossary g
 union
select o.Name 
  from t_diagram d
  join t_diagramobjects dgo 
    on dgo.Diagram_ID = d.Diagram_ID
  join t_object o 
    on o.Object_ID = dgo.Object_ID
where 1=1
   and d.styleEx like '%MDGDgm=Glossary Item Lists::GlossaryItemList;%' 

本次查询的结果

TERM
term1
term2

要求是我在第一个查询的注释中的每个单词下划线,这些单词与第二个查询中的一个术语完全匹配。可以通过将单词括在 <u> </u> 标签

中来添加下划线

所以最终的查询结果应该是

Note
Contains reference to <u>term1</u> and <u>term2</u>
Another note that mentions <u>term1</u>only
A note that doesn't mention any terms

有没有办法在 select 查询中执行此操作? (所以没有变量、临时表、循环和所有这些东西)

在这里,我将 t_object table 的 t_glossary table 列中的所有 TERM 替换为 <ul>Term</ul>

架构:

 create table  t_object(note varchar(500));
 insert into t_object                                    
   select 'Contains reference to term1 and term2' as Note
   union all
   select 'Another note that mentions term1 only'
   union all
   select 'A note that doesn''t mention any terms';
 
                                     
 create table t_glossary (TERM varchar(500));
 insert into t_glossary 
 select 'term1 '
 union all
 select 'term2';

查询:

 WITH  recursive CTE (note, note2, level)  AS
 (
     SELECT note, note , 0 level
     FROM   t_object
 
     UNION ALL
 
     SELECT CTE.note,
        REPLACE(CTE.note2, g.TERM, concat(' <u>', g.term , '</u> ')), CTE.level + 1
     FROM   CTE
     INNER JOIN t_glossary g ON CTE.note2 LIKE concat('%' , g.TERM , '%') and CTE.note2 not like concat('%<u>', g.term , '</u>%')
         
 )
 SELECT DISTINCT note2, note, level
 FROM CTE
 WHERE level =
     (SELECT MAX(level) FROM CTE c WHERE CTE.note = c.note)

输出:

note2 note level
A note that doesn't mention any terms A note that doesn't mention any terms 0
Another note that mentions <u>term1 </u> only Another note that mentions term1 only 1
Contains reference to <u>term1 </u> and <u>term2</u> Contains reference to term1 and term2 2

db<>fiddle here

我认为正则表达式可能是更好的方法。对于您的示例,您需要:

select regexp_replace(note, '(term1|term2)', '<u></u>')
from t_object;

您可以在 MySQL 中轻松地将其构建为:

select regexp_replace(note, pattern, '<u></u>')
from t_object cross join
     (select concat('(', group_concat(term separator '|'), ')') as pattern
      from t_glossary
     ) g;

Here 是一个 db<>fiddle.

正则表达式有一个关键优势,那就是它们可以让您更灵活地处理单词边界。以上替换了任何出现的术语,无论周围的字符如何。但是您可以使用正则表达式的强大功能对其进行调整。

我可能还建议可以在应用程序层使用正则表达式来完成这种替换。