Mysql 从联接表中选择rev_parent_id=0的第一个条目

Mysql 从联接表中选择rev_parent_id=0的第一个条目,mysql,join,greatest-n-per-group,Mysql,Join,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 问题是,对于

又一次参加了最棒的团体聚会

我以前的代码:

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_时间戳,但我尝试使用中的答案,并给我cca 9000和1100000。正确的号码应为cca 422000。也许我没有正确地连接三个表,下面是我的一个尝试,其中一个有9000个结果:

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
file_id=rev_file=文件的id。file_namespace=mimetype文件,0为纯文本。版本id=版本的id。rev_parent_id=父版本的id。rev_timestamp=修订的时间戳


唯一有效的文件是1234,它已被删除并重新创建,因此它有两个rev_parent_id=0条目。我只想在旧版本的父版本id=0修订处于选定时间之间时计算文件的数量。

首先,让我们使用子查询查找每个版本文件修订中最早的时间戳,以满足您的条件

          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 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*而不是COUNTcol。它更快。而且,除非您提到的列可能包含空值,否则它会产生相同的结果。问题中的疑问并非如此

专业提示:始终在联接操作中限定列的大小。文件是重定向,而不是文件是重定向。同样,查询的可读性是动机。如果您有幸有一天让其他人维护您的代码,那么这个人会很高兴看到这一点。这是专业和热心编程的重要组成部分


专业提示:像0这样的数字列会降低性能。它用于匹配文本列,如“%verflo”匹配堆栈溢出。当您在数值列上使用LIKE时,它会将每列的数据类型强制为字符串,然后在其上运行LIKE运算符,从而阻止对数值列使用任何索引。

您应该加入rev_文件的min rev_timestamp子查询

    select count(*) 
    from revisions 
    join files on rev_file = file_id 
    join  (

        select rev_file, min(rev_timestamp) min_time
        from revisions
        where rev_parent_id = 0 
        group  by rev_file

    ) t on t.min_time  = revisions.rev_timestamp 
            and t.rev_file = revisions.rev_file
    where rev_parent_id like 0 
    and rev_timestamp between '20011231230000' and '20191231225959' 
    and file_namespace like 0 
    and file_is_redirect like 0

谢谢大家@scaisedge和@o-jones,最后我使用了你们两个答案的核心并删除了多余的代码,这就是最终对我有效的原因:

select count(*)
  from (select rev_file, min(rev_timestamp) rev_timestamp from revision where rev_parent_id like 0 group by rev_file) revision
  join file on rev_file = file_id
 where rev_timestamp between '20011231230000' and '20191231225959'
   and file_namespace like 0
   and not file_is_redirect;
也许我还可以通过将file_名称空间和file_is_重定向条件移动到join中的另一个子查询中来节省一些运行时间,但也许不行,我不确定


斯凯西奇的答案更简短,可读性更好,因此我立即理解了它,并更喜欢它。斯盖里奇只是在我修正的代码中有一些错误。o-jones的答案更多的是不必要的东西,但是它更详细,以防任何读者需要解释,多亏了改进技巧,我从我的代码中了解了一些计时问题。

更新您的问题添加相关的表架构一个适当的数据样本和预期结果我认为字段的名称很明显,但好的,我编辑了问题。是否有添加表格的选项?Pro tip 2中没有任何内容:我知道,我使用countr1.rev_文件是因为countr1.*不起作用Pro tip 3:文件和修订版在设计上没有类似的命名字段,这就是为什么我不需要在这里麻烦Pro tip 4:我明白,但是像0这样的数字列在SQL这样的语句式语言中可读性更好,它的工作原理与=大多数情况下不在join on中。请查看我的编辑,了解我的专业技巧的详细原因。