【问题标题】:sql compare entries with differents parameterssql比较具有不同参数的条目
【发布时间】:2013-08-19 04:19:25
【问题描述】:

这里我们比较表中的条目

CREATE TABLE a
(id INT PRIMARY KEY,
p1 INT, p2 INT, p3 INT, .. , p15 INT)

p(n) 取值从 0 到 2

我必须获取具有唯一参数组合的所有条目。这不是什么难事,所以我创建了一个这样的表

CREATE TEMPORARY TABLE b AS
(SELECT
        t1.id, 
        t2.p1, t2.p2, t2.p3, t2.p4, t2.p5, t2.p6, t2.p7, t2.p8,
        t2.p9, t2.p10, t2.p11, t2.p12, t2.p13, t2.p14, t2.p15
FROM
(
    SELECT 
        p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15
    FROM
        a
    GROUP BY
        p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15
    HAVING COUNT(*) = 1
)t2
LEFT JOIN a t1 on 
t2.p1 = t1.p1
AND t2.p2 = t1.p2
AND t2.p3 = t1.p3
AND t2.p4 = t1.p4
AND t2.p5 = t1.p5
AND t2.p6 = t1.p6
AND t2.p7 = t1.p7
AND t2.p8 = t1.p8
AND t2.p9 = t1.p9
AND t2.p10 = t1.p10
AND t2.p11 = t1.p11
AND t2.p12 = t1.p12
AND t2.p13 = t1.p13
AND t2.p14 = t1.p14
AND t2.p15 = t1.p15)

这里我们得到具有独特参数组合的 enries。

下一步是针对表 A 中的每条记录,从表 B 中找到所有相差一个、两个和三个参数的记录。单个参数不同的记录不超过一个,两个不同参数的记录不超过两个,以此类推。

例如:

 id  |    p(n)          
-----+----------------    
 1   |000000000000000       
 2   |000000000000001  

我创建了一个临时表格的表格

CREATE TEMPORARY TABLE c AS
(
SELECT
    cnt, id1, id2
FROM
(
    SELECT 
        (t1.p1 = t2.p1)+(t1.p2 = t2.p2)
        +(t1.p3 = t2.p3) +(t1.p4 = t2.p4) +(t1.p5 = t2.p5)
        +(t1.p6 = t2.p6) +(t1.p7 = t2.p7) +(t1.p8 = t2.p8)
        +(t1.p9 = t2.p9) +(t1.p10 = t2.p10) +(t1.p11 = t2.p11)
        +(t1.p12 = t2.p12) +(t1.p13 = t2.p13) +(t1.p14 = t2.p14)
        +(t1.p15 = t2.p15) AS cnt,
        t1.id id1,
        t2.id id2
    FROM 
        b AS t1,
        a AS t2
)
WHERE
    (cnt BETWEEN 12 AND 14)
    AND (id1 < id2)
)

这里我得到一个表,其中包含不同 1、2 和 3 个参数的对

但是我在表中遇到了相当多的问题条目,大约有 100,000 个条目。此表太大(在家用 PC 上处理过的数据),并且表的创建提供了一个很长的表。

也许这是获得所有内容的唯一方法,但是任何人都可以知道解决此问题的分析方法,而不是蛮力夫妇(可能不是 SQL)。当然,这会解决得更快...

任何提示将不胜感激!谢谢!

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

    如果您想要一个只有唯一条目的表,您可以创建第二个表,其中所有列作为复合主键的一部分:

    CREATE TABLE b (
    (id INT, p1 INT, p2 INT, p3 INT, .. , p15 INT)
    PRIMARY KEY (p1, p2, p3, .. , p15))
    IGNORE SELECT * FROM a;
    

    【讨论】:

    • 不是我需要的...我必须删除所有具有相同参数组合的条目,这样只会删除重复项
    【解决方案2】:

    可能不是您问题的完整答案,但如果我有这样的任务,我会尝试的第一件事就是概括查询。当我必须指定超过 3 个类似的列时,这对我来说非常困难,而且很容易出错。
    因此,我建议尝试将您的列转换为行并比较差异,例如(选择您喜欢的任何数据转换方法,我刚刚将联合用于 sqlfiddle,您可以使用hstore 此处发布的PostgreSQL columns to rows with no explicilty specifying column names / columns):

    with cte1 as (
        select id, 'p1' as name, p1 as value from a
        union all
        select id, 'p2' as name, p2 as value from a
        union all
        select id, 'p3' as name, p3 as value from a
        union all
        select id, 'p4' as name, p4 as value from a
    ), cte2 as (
        select
            c1.id, sum(case when c1.value = c2.value then 0 else 1 end) as diff
        from cte1 as c1
             inner join cte1 as c2 on c2.id <> c1.id and c2.name = c1.name
        group by c1.id, c2.id
    )
    select
        id, diff, count(*) as cnt
    from cte2
    group by id, diff
    order by id, diff
    

    我假设你的表没有重复,你可以预先消除它们。

    sql fiddle demo

    更新
    我不知道它是否会帮助你,请看看这个问题PostgreSQL, find strings differ by n characters,我已经要求它尝试帮助你,查看 Erwin Brandstetter 那里的答案。

    我已经为你创建了一个sql fiddle demo,使用不同的方法,看起来使用 levenshtein 是最快的,但它并不比你原来的方法快多少。

    【讨论】:

    • 是的,这是一个更好的解决方案,但问题仍然存在。第二个小时的 MySQL 查询(100,000 个条目)
    • 是的,但不一定。我尝试使用MS SQL Server,但结果是一样的
    猜你喜欢
    • 1970-01-01
    • 2016-09-30
    • 2016-02-23
    • 1970-01-01
    • 1970-01-01
    • 2015-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多