如何在使用 SQL 的重复搜索中排除其他值中的值

Posted

技术标签:

【中文标题】如何在使用 SQL 的重复搜索中排除其他值中的值【英文标题】:How to exclude values within other values in recurrent searches using SQL 【发布时间】:2019-07-31 07:48:01 【问题描述】:

我有一堆与操作系统相关的有效值,我需要检测哪些值显示在特定的文本列中。其中一些只是原始版本的演变,也包括在内,例如 1.'Windows 7 Professional' 和 2.'Windows 7'。

问题是每当我在描述文本中找到#1 时,#2 也会出现,但它不应该出现。

我尝试过标记较大的文本链,只要它们包含较小的记录,但老实说不知道以后如何操作(请参阅此之后的当前查询)。

WITH vv1 (valid_values) AS (
        SELECT 'Windows 7'::text UNION ALL
        SELECT 'Windows 7 Professional'::text UNION ALL
        SELECT 'MacOS'::text UNION ALL
        SELECT 'Linux'::text
        )

    , vv2 AS ( SELECT * FROM vv1 )
    SELECT DISTINCT vv1.valid_values,CASE WHEN vv2.valid_values IS NOT NULL THEN vv2.valid_values END as includes 
    FROM vv1 LEFT OUTER JOIN vv2 ON (LOWER(vv1.valid_values) LIKE LOWER(vv2.valid_values)||'_%')

如果您只执行此查询(不需要 db),您将看到问题。第一行是“Windows 7”。

WITH vv1 (valid_values) AS (
        SELECT 'Windows 7'::text UNION ALL
        SELECT 'Windows 7 Professional'::text UNION ALL
        SELECT 'MacOS'::text UNION ALL
        SELECT 'Linux'::text
        )

, txt (item_description) AS ( SELECT 'Computer with Linux or Windows 7 Professional'::text)

SELECT item_description, valid_values AS detected_os
FROM vv1, txt
WHERE item_description LIKE '%'||valid_values||'%'

预期结果是,当更大的文本链与描述字段中的结果匹配时,不会显示作为更大文本链一部分的有效值。在示例中,“Windows 7”不应是有效输出,因为“Windows 7 Professional”已与项目描述匹配。

【问题讨论】:

【参考方案1】:

我认为您想要最长的匹配值。但是,问题是您需要有效值的类。所以:

WITH vv1 (class, valid_values) AS (
        SELECT 'Windows'::text as class, 'Windows 7'::text UNION ALL
        SELECT 'Windows'::text as class, 'Windows 7 Professional'::text UNION ALL
        SELECT 'Mac'::text, 'MacOS'::text UNION ALL
        SELECT 'Linux'::text, 'Linux'::text
       )
SELECT txt.item_description, MAX(vv1.valid_values) AS detected_os
FROM vv1 JOIN
     txt
     ON txt.item_description LIKE '%' || vv1.valid_values || '%'
GROUP BY txt.item_description, vv1.class;

每个类最多返回一行——匹配最长的那一行。

【讨论】:

效果很好,非常感谢!尽管在您的示例中您忘记声明 item_description :)【参考方案2】:

我会通过将问题表述为返回所有显示为某个其他值的子字符串的有效值来简化您的逻辑:

SELECT valid_values
FROM vv1 t1
WHERE NOT EXISTS (SELECT 1 FROM vv1 t2
                  WHERE t2.valid_values LIKE t1.valid_values || '%' AND
                        t2.valid_values <> t1.valid_values);

Demo

NOT EXISTS 子查询中使用的逻辑只有在对于外部表中的给定有效值,我们能够在同一个 CTE 中找到另一个共享相同前缀的值时才会返回 true 并且 em> 也不等于(这意味着它是当前有效值的超级字符串)。

【讨论】:

以上是关于如何在使用 SQL 的重复搜索中排除其他值中的值的主要内容,如果未能解决你的问题,请参考以下文章

从存储在另一个变量中的值中提取数值[重复]

如何在 PHP 中搜索数组中的多个值?

如何在perl中删除哈希值中的重复值?

sql 2008 查询排除 某一列的数据

选择包含所有提到的值并排除多对多关系中的重复项的名称

如何在 Python 中直接获取字典键作为变量(而不是通过从值中搜索)?