SQL:对重复项进行计数和编号 - 优化相关子查询
SQL: Counting and Numbering Duplicates - Optimising Correlated Subquery
在一个 SQLite 数据库中,我有一个 table,我需要在其中计算某些列(即 3 个特定列相同的行)的重复项,然后对这些情况中的每一个进行编号(即,如果有是特定重复项的 2 次出现,它们需要编号为 1 和 2)。我发现用文字解释有点困难,所以我将在下面使用一个简化的例子。
我的数据类似于以下(第一行是header行,table在下面被引用为"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;
但是 table 有超过 200,000 行(并且数据在 length/content 中是可变的),因此 运行 需要几个小时。 (奇怪的是,当我在 mid-to-late 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" 的子查询,我需要一些帮助来优化它。
简而言之,对于较大的数据集,以下查询 运行s 太慢了:
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;
如何提高上述查询的性能?
它不必以秒为单位 运行,但需要以分钟而不是小时为单位(大约 200,000 行)。
自连接可能比相关子查询更快
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)
上的复合索引
在一个 SQLite 数据库中,我有一个 table,我需要在其中计算某些列(即 3 个特定列相同的行)的重复项,然后对这些情况中的每一个进行编号(即,如果有是特定重复项的 2 次出现,它们需要编号为 1 和 2)。我发现用文字解释有点困难,所以我将在下面使用一个简化的例子。
我的数据类似于以下(第一行是header行,table在下面被引用为"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;
但是 table 有超过 200,000 行(并且数据在 length/content 中是可变的),因此 运行 需要几个小时。 (奇怪的是,当我在 mid-to-late 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" 的子查询,我需要一些帮助来优化它。
简而言之,对于较大的数据集,以下查询 运行s 太慢了:
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;
如何提高上述查询的性能?
它不必以秒为单位 运行,但需要以分钟而不是小时为单位(大约 200,000 行)。
自连接可能比相关子查询更快
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)