【问题标题】:How to exclude values within other values in recurrent searches using SQL如何在使用 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”已与项目描述匹配。

【问题讨论】:

    标签: sql regex amazon-redshift


    【解决方案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> 也不等于(这意味着它是当前有效值的超级字符串)。

    【讨论】:

      猜你喜欢
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      • 2021-10-24
      • 2019-02-07
      • 1970-01-01
      • 1970-01-01
      • 2021-07-03
      • 1970-01-01
      相关资源
      最近更新 更多