SQL:计数和编号重复 - 优化相关子查询(SQL: Counting and Numbering

2019-10-21 16:33发布

在一个SQLite数据库我有一个表,其中我需要计数跨越某些列重复的(其中,3个特定列是相同的,即行),然后还数每一种情况下(即,如果有2次出现的一个特定的重复的,它们需要被编号为1和2)。 我发现它有点难以言传,所以我会在下面用一个简单的例子。

我的数据是类似于以下(第一行的标题行,表在以下作为“idcountdata”提及):

id  match1  match2  match3  data
1   AbCde   BC      0       data01
2   AbCde   BC      0       data02
3   AbCde   BC      1       data03
4   AbCde   AB      0       data04
5   FGhiJ   BC      0       data05
6   FGhiJ   AB      0       data06
7   FGhiJ   BC      1       data07
8   FGhiJ   BC      1       data08
9   FGhiJ   BC      2       data09
10  HkLMop  BC      1       data10
11  HkLMop  BC      1       data11
12  HkLMop  BC      1       data12
13  HkLMop  DE      1       data13
14  HkLMop  DE      2       data14
15  HkLMop  DE      2       data15
16  HkLMop  DE      2       data16
17  HkLMop  DE      2       data17

和输出我需要生成上面会:

id  match1  match2  match3  data    matchid  matchcount
1   AbCde   BC      0       data01  1        2
2   AbCde   BC      0       data02  2        2
3   AbCde   BC      1       data03  1        1
4   AbCde   AB      0       data04  1        1
5   FGhiJ   BC      0       data05  1        1
6   FGhiJ   AB      0       data06  1        1
7   FGhiJ   BC      1       data07  1        2
8   FGhiJ   BC      1       data08  2        2
9   FGhiJ   BC      2       data09  1        1
10  HkLMop  BC      1       data10  1        3
11  HkLMop  BC      1       data11  2        3
12  HkLMop  BC      1       data12  3        3
13  HkLMop  DE      1       data13  1        1
14  HkLMop  DE      2       data14  1        4
15  HkLMop  DE      2       data15  2        4
16  HkLMop  DE      2       data16  3        4
17  HkLMop  DE      2       data17  4        4

以前我是用一对夫妇的相关子查询来实现这一如下:

SELECT id, match1, match2, match3, data,
  (SELECT count(*) FROM idcountdata d2 
    WHERE d1.match1=d2.match1 AND d1.match2=d2.match2 AND d1.match3=d2.match3
      AND d2.id<=d1.id)
  AS matchid,
  (SELECT count(*) FROM idcountdata d2 
    WHERE d1.match1=d2.match1 AND d1.match2=d2.match2 AND d1.match3=d2.match3)
  AS matchcount
FROM idcountdata d1;

但表中有超过20万的行(和该数据的长度可以是/内容可变的),因此这需要小时来运行。 (奇怪的是,当我第一次使用相同的数据相同的查询回中旬至下旬2013年花了几分钟而不是几小时,但这是题外话 - 即使当时我还以为是不雅且效率低下)

我已经在上面的转换的相关子为“matchcount”到不相关子查询与JOIN如下:

SELECT d1.id, d1.match1, d1.match2, d1.match3, d1.data,
  matchcount
FROM idcountdata d1
JOIN
  (SELECT id,match1,match2,match3,count(*) matchcount 
    FROM idcountdata
    GROUP BY match1,match2,match3) d2
  ON (d1.match1=d2.match1 and d1.match2=d2.match2 and d1.match3=d2.match3);

所以它只是“matchid”,我想一些帮助优化子查询。
总之,下面的查询运行速度太慢了更大的数据集:

SELECT id, match1, match2, match3, data,
  (SELECT count(*) FROM idcountdata d2 
    WHERE d1.match1=d2.match1 AND d1.match2=d2.match2 AND d1.match3=d2.match3
      AND d2.id<=d1.id)
  matchid
FROM idcountdata d1;

我怎样才能提高上述查询的性能?
它没有在几秒钟内运行,但它需要几分钟而不是几小时(约为20万行)。

Answer 1:

自加入可能比相关子查询更快

SELECT d1.id, d1.match1, d1.match2, d1.match3, d1.data, count(*) matchid
FROM idcountdata d1
JOIN idcountdata d2 on d1.match1 = d2.match1 
  and d1.match2 = d2.match2 
  and d1.match3 = d2.match3
  and d1.id >= d2.id
GROUP BY d1.id, d1.match1, d1.match2, d1.match3, d1.data

该查询可以采取利用复合指数(match1,match2,match3,id)



文章来源: SQL: Counting and Numbering Duplicates - Optimising Correlated Subquery