我有以下sql查询。它用于获取本周只登录过一次的用户的统计信息。我的问题是我遗漏了一些数据。当我运行一个简单的查询来查看本周只有多少用户登录时,我得到五行但这个查询只返回四行。我认为这是因为这些表只是保持连接状态。当我在查询中创建表时,我遇到了麻烦,并在尝试添加union语句以使其成为完全连接时不断出错。这是查询任何帮助赞赏。
SELECT a.user_id,
a.logins,
a._date,
COALESCE(b.loaded, 0) loaded,
COALESCE(c.attempted, 0) attempted,
COALESCE(d.correct, 0) correct
FROM (SELECT l.user_id,
l.in_datetime,
Date_format(l.in_datetime, '%d/%m/%Y') _date,
Count(*) AS logins
FROM production.login l
GROUP BY user_id) a
LEFT JOIN (SELECT user_id,
Count(*) AS loaded
FROM production.score s
JOIN processedquestion pq
ON s.attempt_id = pq.attempt_id
GROUP BY user_id) b
ON a.user_id = b.user_id
LEFT JOIN (SELECT user_id,
Count(*) AS attempted
FROM production.score s
JOIN processedquestion pq
ON s.attempt_id = pq.attempt_id
WHERE s.selected_answer IS NOT NULL
GROUP BY user_id) c
ON c.user_id = b.user_id
LEFT JOIN (SELECT user_id,
Count(*) AS correct
FROM production.score s
JOIN processedquestion pq
ON s.attempt_id = pq.attempt_id
WHERE s.selected_answer = s.correct_answer
GROUP BY user_id) d
ON c.user_id = d.user_id
WHERE logins = 1
AND Year(a.in_datetime) = Year(Curdate())
AND Week(a.in_datetime) = Week(Curdate())
答案 0 :(得分:1)
我不认为这个问题与完整联接有关。问题是您需要将登录日期过滤器移动到表表达式中。上面的查询会查找在整个表中只有一个登录 的用户,这就是为什么您的结果较少的原因。
另请注意,您的查询无法在正确禁止在分组查询中返回非聚合列的系统上运行。在你的情况下,你只想要一个日期,所以它并不重要;但是,正确的方法是在min()
计算中使用_date
之类的虚拟聚合。我之所以这样称呼它是因为它是MySQL开发人员遇到的许多问题的根源。
单一登录条件也可以用having
表示,这有利于将逻辑的一部分保存在一个地方,而不需要公开单独的计数列以便稍后引用。我认为这可能是一个偏好问题,尽管我认为使用语言中内置的工具是有意义的。
我还将多个联接合并到一个表中,这样可以让它更容易理解。
select
...
from
(
select user_id, min(date_format(in_datetime, '%d/%m/%Y')) _date,
from production.login
where year(in_datetime) = year(curdate()) and week(in_datetime) = week(curdate())
group by user_id
having count(*) = 1
) users
left outer join
(
select
s.user_id, /* I qualified with s but not sure that was the right table */
count(*) as loaded,
count(s.selected_answer) as attempted,
count(case when s.selected_answer = s.corrected_answer then 1 end) as correct
from production.score s inner join processedquestion pq
on pq.attempt_id = s.attempt_id
group by user_id
) questions
on questions.user_id = users.user_id
我不知道您的登录表有多大,但如果您要计算开始日期和结束日期并使用in_datetime between <start_of_week> and <end_of_week>
而不是基于提取年份和星期部分的检查,则查询可能会更有效地运行。实际上,当你在1月的第一周使用它时,我认为你会遇到更严重的问题。