从一个查询中的user_id分组的mysql中的多个表中计算不同的总数

时间:2015-07-10 11:37:28

标签: mysql sql

我想从courses_takenquiz_attempts表中计算user_id,但我的查询给我的数字错误。

SELECT 
    u.id,
    u.email,
    u.user,
    u.joined,
    MAX(qa.last_attempt_time) as last_attempt_time, 
    COUNT(qa.user_id) total_quiz, 
    COUNT(ct.user_id) total_courses 
FROM users u

LEFT JOIN courses_taken ct
ON u.id = ct.user_id

LEFT JOIN quiz_attempt qa
ON u.id = qa.user_id AND qa.attempt_mode=1

GROUP BY u.id
ORDER BY total_courses DESC

表格结构

users

id, email, user, joined

quiz_attempt

id,user_id, last_attempt_time, attempt_mode etc.

courses_taken

id,user_id,course_id,taken_on etc.

在这里,我试图让所有用户获得测验总数和课程总数。但我的查询会为测验尝试和所采取的课程返回相同的数字。

3 个答案:

答案 0 :(得分:0)

您可以做的是在列上使用COUNT DISTINCT,该列与您尝试计算的值唯一不同,即:

...
COUNT(DISTINCT qa.id) total_quiz, 
COUNT(DISTINCT ct.course_id) total_courses 
...

SqlFiddle here

答案 1 :(得分:0)

由于加入,您可能会遇到笛卡尔积问题。更好的解决方案是预先汇总结果。但是,在许多情况下,如果表格不是太大,那么count(distinct)可以解决问题:

SELECT u.id, u.email, u.user, u.joined,
       MAX(qa.last_attempt_time) as last_attempt_time, 
       COUNT(DISTINCT qa.id) as total_quiz, 
       COUNT(DISTINCT ct.id) as total_courses 
FROM users u LEFT JOIN
     courses_taken ct
     ON u.id = ct.user_id LEFT JOIN
     quiz_attempt qa
     ON u.id = qa.user_id AND qa.attempt_mode = 1
GROUP BY u.id
ORDER BY total_courses DESC;

请注意,这是有效的,因为您使用的是MAX()COUNT()。它不适用于SUM()AVG()

答案 2 :(得分:0)

你不应该在user_ID列上添加distinct,而是将它放在该表的id上,如下所示:

SELECT u.id, u.email, u.userid, u.joined,
MAX(qa.last_attempt_time) as last_attempt_time, 
COUNT(DISTINCT qa.id) as total_quiz, 
COUNT(DISTINCT ct.id) as total_courses 
FROM users u LEFT JOIN
courses_taken ct
ON u.id = ct.user_id LEFT JOIN
quiz_attempt qa
ON u.id = qa.user_id AND qa.attempt_mode = 1
GROUP BY u.id, u.email, u.userid, u.joined
ORDER BY total_courses DESC;

或者如果这让您感到困惑,可以使用这样的子查询: -

SELECT 
u.id,
u.email,
u.UserId,
u.joined,
qa.last_attempt_time as last_attempt_time, 
qa.total_quizCOUNT,
ct.total_coursesCOUNT 
FROM users u

LEFT JOIN 
(Select user_id, Count(user_id) as total_coursesCOUNT from courses_taken group by user_id) ct
ON u.id = ct.user_id

LEFT JOIN (Select user_id, Count(user_id) total_quizCOUNT, MAX(last_attempt_time) as last_attempt_time from quiz_attempt  where attempt_mode = 1 group by user_id) qa
ON u.id = qa.user_id

ORDER BY total_coursesCOUNT DESC