【问题标题】:SQL .How to find records with almost identical string values?SQL .如何查找具有几乎相同字符串值的记录?
【发布时间】:2020-07-28 21:04:41
【问题描述】:

假设我有这张表(产品):

part_number   product_name
1202          airpods
1204          ipod
1398          iphone 6
1304          watch I
1378          iphone 7
1244          airpods 2

我想选择除第三个字符外,part_number 至少有一个(几乎完美)匹配的所有记录。所以最终的结果应该是这样的:

part_number   product_name
1204          ipod
1398          iphone 6
1378          iphone 7
1244          airpods 2

有没有办法使用 LIKE 运算符来做到这一点?我知道 LIKE 在陈述几个已知字符时可以找到模式,但在这种情况下,我不一定知道它们是什么。

注意:是的,part_number 字段定义为字符串,而不是数字。

【问题讨论】:

    标签: sql database string sqlite subquery


    【解决方案1】:

    我了解您希望存在另一行且部件号部分匹配的行:前两位数和最后一位应匹配,而第三位不同。

    您可以使用exists。假设 part_number 是一个整数(因为它应该是),你可以用算术来做到这一点:

    select p.*
    from products p
    where exists (
        select 1
        from products p1
        where 
            p1.part_number <> p.part_number
            and p1.part_number / 100 = p.part_number / 100
            and p1.part_number - p1.part_number / 10 * 10 = p.part_number - p.part_number / 10 * 10
    )
    

    您还可以使用字符串函数 - 这使得查询更易于理解(尽管效率可能较低):

    select p.*
    from products p
    where exists (
        select 1
        from products p1
        where 
            p1.part_number <> p.part_number
            and substr(p1.part_number, 1, 2) = substr(p.part_number, 1, 2)
            and substr(p1.part_number, 4, 1) = substr(p.part_number, 4, 1)
    )
    

    Demo on DB Fiddle - 两个查询结果:

    零件号 |产品名称 :------------ | :----------- 第1204章iPod 第1398章iPhone 6 第1378章苹果手机 7 第1244章气垫 2

    【讨论】:

    • 非常感谢。这正是我想要的。就我而言,字符串解决方案是完美的,因为有一些包含字母的 part_numbers 记录,即 12#7。
    【解决方案2】:

    手头没有 SQLite,但在大多数 SQL 变体中这都有效:

    select * from test t1 where exists
    (
     select * from test t2 where t2.part_number != t1.part_number 
     and left(t1.part_number,2) = left(t2.part_number,2)
     and right(t1.part_number,1) = right(t2.part_number,1)
    )
    

    【讨论】:

    • 谢谢。我将在 SQL Server 中尝试这个
    【解决方案3】:

    可以使用COUNT()窗口函数:

    select part_number, product_name
    from (
      select *, 
        count(*) over (partition by substr(part_number, 1, 2), substr(part_number, -1)) counter
      from products
    )
    where counter > 1
    

    请参阅demo
    结果:

    | part_number | product_name |
    | ----------- | ------------ |
    | 1204        | ipod         |
    | 1244        | airpods 2    |
    | 1398        | iphone 6     |
    | 1378        | iphone 7     |
    

    【讨论】:

    • 有趣!我没有想过为此使用 COUNT()
    • @Mafe 这是最高效的方法。我很惊讶你选择了如此复杂的方式。
    猜你喜欢
    • 2020-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-17
    • 1970-01-01
    • 2015-04-21
    • 1970-01-01
    相关资源
    最近更新 更多