使用字符串匹配来减少查询结果

时间:2012-11-10 15:48:13

标签: mysql sql

我的表格格式为:

Id     | Loc |
-------|-----|
789-A  | 4   |
123    | 1   |
123-BZ | 1   |
123-CG | 2   |
456    | 2   |
456    | 3   |
789    | 4   |

我想根据是否存在重复,从查询结果中排除某些行。但是,在这种情况下,重复行的定义非常复杂:

如果查询返回的任何行(让我们将此假设行称为ThisRow),则查询结果中还包含对应的行 其中{ {1}}与Loc相同而ThisRow.Loc的格式为Id,则<ThisRow.Id>-<an alphanumeric suffix>应视为重复,并从查询结果中排除。

例如,使用上表,ThisRow应返回以下结果集:

SELECT * FROM table

我理解如何编写匹配条件的字符串:

Id     | Loc |
-------|-----|
789-A  | 4   |
123-BZ | 1   |
123-CG | 2   |
456    | 2   |
456    | 3   |

ThisRow.Id REGEXP '^PossibleDuplicateRow.Id-[A-Za-z0-9]*'

的直接比较
Loc

我不明白的是如何将这些条件形成为(自引用?)查询。

2 个答案:

答案 0 :(得分:3)

这是一种方式:

SELECT *
FROM myTable t1
WHERE NOT EXISTS
(
    SELECT 1
    FROM myTable t2
    WHERE t2.Loc = t1.Loc
    AND t2.Id LIKE CONCAT(t1.Id, '-%')
)

SQL Fiddle example

或者,使用反连接的相同查询(应该更快一点):

SELECT *
FROM myTable t1
LEFT OUTER JOIN myTable t2 
    ON t2.Loc = t1.Loc
    AND t2.Id LIKE CONCAT(t1.Id, '-%')
WHERE t2.Id IS NULL

SQL Fiddle example

答案 1 :(得分:0)

在您提供的示例数据中,没有重复的位置在重复行上的示例。例如,您没有“123-AZ,1”行,其中前缀行“123,1”将与两行冲突。

如果这是数据的真实特征,那么您可以通过使用聚合来消除没有自联接的重复:

select max(id), loc
from t
group by (case when locate(id, '-') = 0 then id
               else left(id, locate(id, '-') - 1)
          end), loc

我提供这个是因为聚合应该比非等值连接快得多。