在两个表之间匹配多组值,寻求一种高效且易于维护的方法

后端开发 2026-07-08

我有以下两张表:

表article_description:

文章代码 区域 描述
0001 EN 示例描述,可能包含关键字ASC
0001 NL 虚拟描述,带有关键字ASC
1234 EN 示例描述ASC,可能包含关键字
1234 NL 虚拟描述ASC,带有关键字
4567 EN 示例描述,没有关键字
5678 EN 描述,包含其他关键字FT

表article_labels:

文章代码 区域 标签代码
0001 EN QM0029
0001 NL QM0029

我想通过将article_description中出现的关键词与另一张表中存在的质量标签进行对比,来识别可能缺失标签代码的article_code。(遗憾的是,我们缺少其他更强健的信息来进行更好的检查。)
一个示例关键词是 "ASC";描述中包含该关键词的每条目都应对应标签 "QM0029"。我大约有30对标签与关键词。
我在努力写出一个可维护、能实现此逻辑的查询,但还没有想出一个既高效又优雅的实现方式。
我最初先写了一个查询来处理单对的情况,通过正则表达式匹配独立的模式(见下面的代码)。
我希望能把查询扩展成能覆盖所有关键词对的情形,但不确定如何以高效的方式实现。也许把下面的查询复制多次并用UNION ALL是最简单的办法,但可维护性很差。有没有更好的办法?

可能有帮助的一些说明:

  • 我希望返回每个至少有一个区域缺失标签的article_code
  • 描述总是大写;因此搜索时不需要区分大小写。描述中应仅包含(大写)字母和/或数字
  • 原则上,每个article_code要么有0 个要么只有1 个质量标签,但如果能对多标签的情况具有鲁棒性会是加分项
  • 约有100,000条不同的article_code,和5 个不同的区域locales。希望有一定的效率
  • 我把一个关键词视为若与其他单词至少用一个空格分隔即可出现(可以出现在中间、开头或结尾)
  • 根据示例表,我预计会返回article_code 1234和 5678。它们在至少一个描述中包含关键字 "ASC" 和 "FT",但没有对应的标签。1234应该有QM0029标签;5678应该有与FT对应的质量标签(20种可能之一)。
  • 预期输出:
文章代码 检查结果
1234 ASC标签缺失
5678 FT标签缺失

如果你有任何问题,或对本文的改进有建议,请告诉我。另外,我的SQL还不是很熟练,任何其他改进/建议也将不胜感激。

Cheers!

WITH article_labels AS (
  SELECT article_code, locale, label_code
  FROM article_label
  WHERE label_code = 'QM0029'
),
article_descriptions AS (
  SELECT article_code, locale
  FROM article_description
  WHERE article_description ~ '(^| )ASC( |$)'
  AND article_description IS NOT NULL
)
SELECT DISTINCT t1.article_code, 'ASC label missing' AS check_value
FROM article_descriptions AS t1
LEFT JOIN article_labels AS t2
ON 
  t1.article_code = t2.article_code
  AND
  t1.locale = t2.locale
WHERE t2.label_code IS NULL

表中包含我所有标签/关键词对的表:

标签 关键词
QM_0029 ASC
QM_0031 BIO
QM_0037 BIO
QM_0197 BIO
QM_0228 BIO
QM_0244 BIO
QM_0622 BIO
QM_0053 BL1*
QM_0054 BL2*
QM_0055 BL3*
QM_0253 FT
QM_0258 FT
QM_0259 FT
QM_0697 FT
QM_0698 FT
QM_0699 FT
QM_0700 FT
QM_0701 FT
QM_0702 FT
QM_0703 FT
QM_0704 FT
QM_0705 FT
QM_0706 FT
QM_0707 FT
QM_0708 FT
QM_0709 FT
QM_0710 FT
QM_0711 FT
QM_0712 FT
QM_0713 FT
QM_0695 GGN
QM_0423 MSC

解决方案

First, about keyword search.
You can check each keyword as shown in your example using regexp.
Or you can split the "description" into separate words and search for a match (equality).
In my example used "string_to table" function to split description to words and then comparing with keywors for JOIN.

First part of query (splitting)

select *
from article_description ad
cross join lateral string_to_table(article_description,' ')w(word)

For first row we get

文章代码 区域 描述 单词
0001 EN 示例描述,可能包含关键字ASC SAMPLE
0001 EN 示例描述,可能包含关键字ASC DESCRIPTION
0001 EN 示例描述,可能包含关键字ASC THAT
0001 EN 示例描述,可能包含关键字ASC MAY
0001 EN 示例描述,可能包含关键字ASC CONTAIN
0001 EN 示例描述,可能包含关键字ASC A
0001 EN 示例描述,可能包含关键字ASC KEYWORD
0001 EN 示例描述,可能包含关键字ASC ASC

Next join (INNER) table "article_labels" to splitted words on "al.label_code=lk.label_code"

select *
from article_description ad
cross join lateral string_to_table(article_description,' ')w(word)
inner join label_keywords lk on lk.keyword=w.word
文章代码 区域 描述 单词 标签代码 关键词
0001 EN 示例描述,可能包含关键字ASC ASC QM_0029 ASC
0001 NL 虚拟描述,带有关键字ASC ASC QM_0029 ASC
1234 EN 示例描述ASC,可能包含关键字 ASC QM_0029 ASC
1234 NL 虚拟描述ASC,带有关键字 ASC QM_0029 ASC

Finally, we LEFT join existing pairs (label_code,keyword). If pair not exists,article_labels.article_code is null.

After JOIN we filter not matching rows (antijoin) by "where al.article_code is null"

With anti JOIN

select *
from article_description ad
cross join lateral string_to_table(article_description,' ')w(word)
inner join label_keywords lk on lk.keyword=w.word
left join article_labels al on al.label_code=lk.label_code and al.article_code=ad.article_code
   and al.locale=ad.locale
where al.article_code is null
;

Or with NOT EXISTS.

There we consider only articles, not having reference in "article_labels" table by columns(article_code,locale)

select *
from article_description ad
cross join lateral string_to_table(article_description,' ')w(word)
inner join label_keywords lk on lk.keyword=w.word
left join article_labels al on al.label_code=lk.label_code and al.article_code=ad.article_code
   and al.locale=ad.locale
where  not exists (select 1 from article_labels al2 where al2.article_code=ad.article_code and al2.locale=ad.locale)
文章代码 区域 描述 单词 标签代码 关键词 文章代码 区域 标签代码
1234 EN 示例描述ASC,可能包含关键字 ASC QM_0029 ASC
1234 NL 虚拟描述ASC,带有关键字 ASC QM_0029 ASC
5678 EN 描述,包含其他关键字FT FT QM_0713 FT
5678 EN 描述,包含其他关键字FT FT QM_0712 FT
5678 EN 描述,包含其他关键字FT FT QM_0711 FT
5678 EN 描述,包含其他关键字FT FT QM_0710 FT
5678 EN 描述,包含其他关键字FT FT QM_0699 FT
5678 EN 描述,包含其他关键字FT FT QM_0698 FT
5678 EN 描述,包含其他关键字FT FT QM_0697 FT
5678 EN 描述,包含其他关键字FT FT QM_0259 FT
5678 EN 描述,包含其他关键字FT FT QM_0258 FT
5678 EN 描述,包含其他关键字FT FT QM_0253 FT

示例

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章