【问题标题】:Mysql COUNT(*) on multiple tables多个表上的 Mysql COUNT(*)
【发布时间】:2009-06-03 10:44:24
【问题描述】:

这个查询有什么问题:

SELECT co.*, mod.COUNT(*) as moduleCount, vid.COUNT(*) as vidCount 
 FROM courses as co, modules as mod, videos as vid 
 WHERE mod.course_id=co.id AND vid.course_id=co.id ORDER BY co.id DESC

换句话说,对于从“课程”返回的每条记录,我该如何做到这一点,有 一个名为“modCount”的附加列显示了该 course_id 在模块表中的记录数,另一个名为“vidCount”的列对视频表执行相同的操作。

错误:

错误号:1064

您的 SQL 语法有错误; 检查对应的手册 您的 MySQL 服务器版本 在 ') 附近使用的正确语法 moduleCount, vid.COUNT() as vidCount FROM courses as co, ' 第 1 行

【问题讨论】:

    标签: sql mysql


    【解决方案1】:

    使用子选择可以做到:

    SELECT co.*, 
        (SELECT COUNT(*) FROM modules mod WHERE mod.course_id=co.id) AS moduleCount, 
        (SELECT COUNT(*) FROM videos vid WHERE vid.course_id=co.id) AS vidCount
    FROM courses AS co
    ORDER BY co.id DESC
    

    但要小心,因为当课程有很多行时,这是一个昂贵的查询。

    编辑: 如果您的表非常大,那么以下查询应该会执行得更好(有利于更复杂的阅读和理解)。

    SELECT co.*, 
        COALESCE(mod.moduleCount,0) AS moduleCount,
        COALESCE(vid.vidCount,0) AS vidCount
    FROM courses AS co
        LEFT JOIN (
                SELECT COUNT(*) AS moduleCount, course_id AS courseId 
                FROM modules
                GROUP BY course_id
            ) AS mod
            ON mod.courseId = co.id
        LEFT JOIN (
                SELECT COUNT(*) AS vidCount, course_id AS courseId 
                FROM videos
                GROUP BY course_id
            ) AS vid
            ON vid.courseId = co.id
    ORDER BY co.id DESC
    

    【讨论】:

    • 费用是需要牢记的重要事项,尤其是有几个子选择时。
    • 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以获取正确的语法,以便在第 2 行的 'mod WHERE mod.course_id=co.id) as moduleCount, (SELECT COUNT(*)' 附近使用
    • 还有一个不属于那里的“WHERE”。请再试一次。如果这不起作用,您的 MySQL 服务器不支持标量子选择。你用的是哪个版本?
    • 我想我正在使用 mysql 5。我确实在没有 where 的情况下尝试过,但它仍然没有工作
    • MySQL 5 应该没问题。你在运行 ANSI 模式吗?
    【解决方案2】:

    我有更好的解决方案和简单的

    SELECT COUNT(*),(SELECT COUNT(*) FROM table2) FROM table1
    

    【讨论】:

      【解决方案3】:
      SELECT co.*,
             (
             SELECT  COUNT(*)
             FROM    modules mod
             WHERE   mod.course_id = co.id
             ) AS modCount,
             (
             SELECT  COUNT(*)
             FROM    videos vid
             WHERE   vid.course_id = co.id
             ) AS vidCount
      FROM   courses co
      ORDER BY
              co.id DESC
      

      【讨论】:

        【解决方案4】:
        SELECT co.*, m.ModCnt as moduleCount, v.VidCnt as vidCount 
        FROM courses co
        INNER JOIN (
                select count(*) AS ModCnt, co.id AS CoID
                from modules 
                group by co) m
            ON m.CoID = co.id
        INNER JOIN (
                select count(*) AS VidCnt, co.id AS CoID
                from videos
                group by co) v
            ON v.CoID = co.id   
        INNER JOIN videos vid 
            ON vid.course_id = co.id 
        ORDER BY co.id DESC
        

        【讨论】:

        • 我刚刚注意到这一点,modcnt,哈哈。是否允许在工作相关代码中使用“cnt”作为简写? :D
        【解决方案5】:

        拍这个。我用一些非mysql代码完成了这项工作:

        function getAllWithStats($info='*',$order='',$id=0)
        {
            $courses=$this->getAll($info,$order,$id);
        
            foreach ($courses as $k=>$v)
            {
                $courses[$k]['modCount']=$this->getModuleCount($v['id']);
                $courses[$k]['vidCount']=$this->getVideoCount($v['id']);
            }
        
            return $courses;
        }
        

        【讨论】:

        • 这与子选择解决方案基本相同。您正在为课程表中的每一行执行两个额外的查询,如果课程表不是很大,这不是很成问题。
        • 查看 subselect 解决方案和 PHP 解决方案可能会很有趣,它们的性能会更好。尽管 PHP 解决方案将有一些网络开销,因为数据必须在线传输,但子选择解决方案将受到其子选择缺少 MySQL 查询缓存的影响——尽管完整的查询将被缓存在查询缓存中。
        猜你喜欢
        • 2016-02-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-22
        • 1970-01-01
        • 1970-01-01
        • 2012-10-27
        • 2011-12-25
        • 1970-01-01
        相关资源
        最近更新 更多