【问题标题】:combining multiple counts into one query - group by将多个计数组合到一个查询中 - 分组依据
【发布时间】:2011-07-12 14:51:33
【问题描述】:

我想将 3 个 SELECT 语句合并为一个:

SELECT COUNT(A.id), CONCAT(B.fname,' ', B.lname) AS fullname 
FROM feedbacks A 
    INNER JOIN users B 
         ON A.userid = B.userid 
WHERE DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' 
GROUP BY fullname

SELECT COUNT(A.id), CONCAT(B.fname,' ', B.lname) AS fullname 
FROM feedbacks A 
    INNER JOIN users B 
        ON A.userid = B.userid 
WHERE status = 'C' 
AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' 
GROUP BY fullname`

SELECT COUNT(A.id), CONCAT(B.fname,' ', B.lname) AS fullname 
FROM feedbacks A 
    INNER JOIN users B ON A.userid = B.userid 
WHERE caused_change = 1 
AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' 
GROUP BY fullname

但组合它们似乎总是返回错误:(操作数应包含 1 列)

SELECT 
(SELECT COUNT(A.id), CONCAT(B.fname,' ', B.lname) AS fullname FROM feedbacks A INNER JOIN users B ON A.userid = B.userid WHERE DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' GROUP BY fullname) AS T1,  
(SELECT COUNT(A.id), CONCAT(B.fname,' ', B.lname) AS fullname FROM feedbacks A INNER JOIN users B ON A.userid = B.userid WHERE status = 'C' AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' GROUP BY fullname) AS T2,  
(SELECT COUNT(A.id), CONCAT(B.fname,' ', B.lname) AS fullname FROM feedbacks A INNER JOIN users B ON A.userid = B.userid WHERE caused_change = 1 AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' GROUP BY fullname) AS T3

所以我尝试从各个语句中删除 JOIN 和 GROUP:

SELECT CONCAT(B.fname, ' ', B.lname) AS fullname,
(SELECT COUNT(A.id) FROM feedbacks A WHERE DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11') AS T1,  
(SELECT COUNT(A.id) FROM feedbacks A WHERE status = 'C' AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11') AS T2,
(SELECT COUNT(A.id) FROM feedbacks A WHERE caused_change = 1 AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11') AS T3
FROM feedbacks 
    INNER JOIN users B 
        ON feedbacks.userid = B.userid 
GROUP BY fullname

但这会返回所有内容的总数与用户细分(因为计数在 where 子句中没有说明用户 ID 或全名,毫无疑问)。

我觉得我很接近但错过了一些东西。谁能在这里指出我正确的方向?我只是想知道我做错了什么。

感谢您的宝贵时间。

【问题讨论】:

    标签: mysql sql count group-by


    【解决方案1】:

    最好的方法是使用条件SUM

    SELECT CONCAT(B.fname, ' ', B.lname) AS fullname,
           SUM(
               CASE WHEN DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' 
               THEN 1 ELSE 0 END
           ) AS T1,
           SUM(
               CASE WHEN status = 'C' 
                     AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' 
               THEN 1 ELSE 0 END
           ) AS T2,
           SUM(
               CASE WHEN caused_change = 1 
                     AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' 
               THEN 1 ELSE 0 END
           ) AS T3
    FROM feedbacks 
        INNER JOIN users B 
            ON feedbacks.userid = B.userid 
    GROUP BY fullname
    

    【讨论】:

    • 谢谢!事实证明,这在今天非常有用。
    【解决方案2】:

    我不知道您是否可以将这 3 个查询合并为一个统一查询。您有 3 个重叠的“where 子句”:

    第一个查询:日期范围内的所有记录
    第二个查询:所有在日期范围内但状态='C'的记录
    第三个查询:所有在日期范围内但也有 cause_change=1 的记录

    从逻辑上讲,第一个查询已经包含了来自第二个和第三个查询的所有记录,因此您将重复计算来自 #2 和 #3 的结果。

    但是,如果您确实想将所有三个组合成一个结果,请执行外部查询方法:

    SELECT sum(cnt), fullname
    FROM (
        SELECT COUNT(A.id) as cnt, CONCAT(B.fname,' ', B.lname) AS fullname
        FROM feedbacks A
        INNER JOIN users B ON A.userid = B.userid
        WHERE DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11'
        GROUP BY fullname
    
        UNION
    
        ...
        WHERE status = 'C' AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11'
    
        UNION
    
        ...
        WHERE caused_change = 1 AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11'
    ) AS innerquery
    GROUP BY fullname
    

    注意第一个内部查询中count() 的别名。这是为了使计数字段在外部查询中显示为“cnt”。

    【讨论】:

    • 我之前抓取了该日期范围内的所有结果,并使用 PHP 来执行逻辑和计数。有人建议我让数据库做繁重的工作。感谢您花时间解释。
    【解决方案3】:

    UNION 和 SUM 应该可以完成这项工作。您的代码应如下所示:

     select sum(x.col1), x.fullname
    from
    (SELECT COUNT(A.id)as col1, CONCAT(B.fname,' ', B.lname) AS fullname FROM feedbacks A INNER JOIN users B ON A.userid = B.userid WHERE DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' GROUP BY fullname
    UNION
    SELECT COUNT(A.id)as col1, CONCAT(B.fname,' ', B.lname) AS fullname FROM feedbacks A INNER JOIN users B ON A.userid = B.userid WHERE status = 'C' AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' GROUP BY fullname
    UNION
    SELECT COUNT(A.id)as col1, CONCAT(B.fname,' ', B.lname) AS fullname FROM feedbacks A INNER JOIN users B ON A.userid = B.userid WHERE caused_change = 1 AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' GROUP BY fullname
    )x
    group by x.fullname
    

    【讨论】:

      猜你喜欢
      • 2014-06-22
      • 2021-11-04
      • 1970-01-01
      • 2018-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-21
      相关资源
      最近更新 更多