开发者

combining multiple counts into one query - group by

I have 3 SELECT statements I'd like to combine into one:

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.开发者_如何学JAVAid), 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

But combining them always seems to return an error: (Operand should contain 1 column(s))

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

So I tried removing the JOIN and GROUP from the individual statements to make:

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

But that returns totals for everything vs. breakdown by user (because the counts don't say anything about userid or fullname in the where clause, no doubt).

I feel like I'm close but missing something. Can anyone point me in the correct direction here? I'm just trying to learn what I'm doing wrong.

Thank you for your time.


The best way is to use a conditional 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


I don't know if you can combine those 3 queries into a single unified query. You've got 3 'where clauses' that overlap:

first query: ALL records that fall in the date range
second query: ALL records that fall in the date range but also have status='C'
third query: ALL records that fall in the date range but also have caused_change=1

In logical terms, the first query already contains all the records from the second and third queries, so you'd be double counting the results from #2 and #3.

However, if you do want to combine all three into a single result, then do the outer query method:

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

Note the alias on the count() in the first inner query. That's to make the counted field appear as 'cnt' for the outer query.


UNION and SUM should do the work. Your code should look like this:

 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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜