mysql - 从连接表中选择 rev_parent_id=0 的第一个条目

标签 mysql join greatest-n-per-group

#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 columnSelect 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/

相关文章:

php - 如何在 jQuery Mobile 页面中提交表单?

mysql - SQL 按升序/降序排序

mysql - 是否有任何版本的 SQL 允许这种连接?

SQL查询列出具有连接的父亲和 child ,如何区分它们?

mysql - 创建新表时插入另一个表中的值

mysql - 传输mysql Access 包括关系和外键?

mySQL 到 SQL 迁移

MySQL - 按单独表中的值排序

sql - 在 Postgres 中查找 min + 1

mysql - MySQL 中的 ROW_NUMBER()