#greatest-n-per-group 派对的又一个!
我以前的代码:
select count(*)
from revisions join files on rev_file = file_id
where rev_parent_id like 0
and rev_timestamp between '20011231230000' and '20191231225959'
and file_namespace like 0
and file_is_redirect like 0
问题是,对于某些文件,有多个 rev_parent_id=0 的条目。我想只计算那些最早的 rev_timestamp,但我尝试使用 SQL select only rows with max value on a column 和 Select Earliest Date and Time from List of Distinct User Sessions 中的答案给了我 cca 9 000 和 11 000 000。正确的数字应该是 cca 422 000。也许我没有正确加入三个表,在这里是我的尝试之一(有 9 000 个结果):
select count(r1.rev_file)
from revisions r1
left outer join revisions r2 on (r1.rev_file = r2.rev_file
and r1.rev_timestamp < r2.rev_timestamp)
join files on r1.rev_file = file_id
where r2.rev_file is NULL
and r1.rev_parent_id like 0
and r1.rev_timestamp between '20011231230000' and '20191231225959'
and file_namespace like 0
and file_is_redirect like 0
表结构:
files
file_id, file_namespace, file_is_redirect
1234, 0, 0
1235, 3, 1
1236, 3, 0
revisions
rev_file, rev_id, rev_parent_id, rev_timestamp
1234, 19, 16, 20170302061522
1234, 16, 0, 20170302061428
1234, 14, 12, 20170302061422
1234, 12, 0, 20170302061237
1235, 21, 18, 20170302061815
1235, 18, 13, 20170302061501
1235, 13, 8, 20170302061355
1235, 8, 3, 20170302061213
1235, 3, 0, 20170302061002
1236, 6, 0, 20170302061014
file_id = rev_file = 文件的 ID。 file_namespace = 文件的 mimetype,0 为明文。 rev_id = 修订版的 id。 rev_parent_id = 父版本的 id。 rev_timestamp = 修订的时间戳
唯一有效的文件是 1234,它已被删除并重新创建,因此它有两个 rev_parent_id=0 条目。仅当较旧的 rev_parent_id=0 修订版在选定时间之间时,我才想对文件进行计数。
最佳答案
首先,让我们使用子查询为每个 rev_file
找到 revisions
中最早的时间戳,以满足您的条件。
SELECT MIN(rev_timestamp) rev_timestamp, rev_file
FROM revisons
WHERE rev_parent_id like 0
AND rev_timestamp between '20011231230000' and '20191231225959'
GROUP BY rev_file
这会为您提供一个虚拟表,其中包含符合您条件的每个文件的最早时间戳。
接下来,像这样将该表连接到您的其他表
SELECT COUNT(*) count
FROM revisions r1
JOIN (
SELECT MIN(rev_timestamp) rev_timestamp, rev_file
FROM revisons
WHERE rev_parent_id like 0
AND rev_timestamp between '20011231230000' and '20191231225959'
GROUP BY rev_file
) rmin ON r1.rev_timstamp = rmin.rev_timestamp
AND r1.rev_file = rmin.rev_file
JOIN files f ON r1.rev_file = file_id
and f.file_namespace like 0
and f.file_is_redirect like 0
专业提示:格式化您的查询以使其易于阅读是值得的。总是麻烦。
专业提示:尽可能使用COUNT(*)
而不是COUNT(col)
。它更快。而且,除非您提到的 col
可能包含 NULL 值,否则它会产生相同的结果。问题中的查询并非如此。
专业提示:始终在 JOIN 操作中限定您的列(f.file_is_redirect
而不是 file_is_redirect
)。同样,查询的可读性是动机。如果有一天你有幸让别人维护你的代码,那个人会很高兴看到这一点。这是“专业和爱好者”编程的重要组成部分。
专业提示:numeric_col LIKE 0
会降低性能。它用于匹配文本(column LIKE '%verflo'
匹配 Stack Overflow
)。当您在数字列上使用 LIKE
时,它会将每列的数据类型强制转换为字符串,然后对其运行 LIKE
运算符,从而阻止您使用任何索引在数字列上。
关于mysql - 从连接表中选择 rev_parent_id=0 的第一个条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54748335/