MySQL离开了join子查询的null join

时间:2014-03-11 14:51:11

标签: mysql join null subquery

好的,所以我有一个相当详细的SQL查询,我有2个表,第一个表包含家庭作业数据。第二个表包含为课程设置的班级中每个学生的记录。

我想计算第二张桌子上的一些数据,这些数据符合某些条件,例如,发出了多少学生作业,计算了多少学生已经返回作业,并计算了多少作业被教师。

我会在这篇帖子的底部发布我的查询。

我在2个左连接上使用子查询。子查询看起来像这样:

LEFT JOIN (
    SELECT homework_id, COUNT(uid) AS total_returned
    FROM tbl_homework_student_log 
    WHERE homework_completed = 1
) r2 ON r2.homework_id = h.uid

在上面的示例中,学生日志表包含索引homework_id,该索引链接回主要作业表的唯一索引h.uid

当这种情况有效时,我的问题出现了:

1)如果COUNT(uid)等于0,则homework_id为NULL

2)查询产生以下结果

 r2.homework_id   |  total_returned (COUNT(uid))
------------------+------------------------------
 NULL             | 0

我的加入失败,出现以下错误消息:

Column 'homework_id' cannot be null - (r2 ON r2.homework_id (null) = h.uid)

我不知道如何解决这个问题。我最初在SELECT子句中使用了子查询,但我想在LEFT JOIN中使用它。

我的问题是如何确保r2.homework_id永远不会为空? 我尝试过以下方法:

  • 从连接子查询中删除COUNT()函数并将它们移动到主选择子句 - 不按预期工作
  • 将每个联接子查询中的where子句移动到其关联的ON子句 - 不能正常工作
  • 尝试将AND r2.homework_id IS NOT NULL添加到相应的ON条款中 - 无法正常工作
  • 尝试将AND COUNT(uid)>0添加到加入子查询中的WHERE子句中 - 不能正常工作

我完全没有想法。

这是我的全部问题:

SELECT h.uid, h.class_id, h.homework_details, h.require_upload_return,
       CONCAT(u.surname, ', ', u.forename) AS teacher_name, 
       DATE_FORMAT(h.set_date, '%D %M %Y') AS set_date_DMY,
       DATE_FORMAT(h.set_date, '%b %e, %Y') AS set_date_beY,
       UNIX_TIMESTAMP(h.set_date) AS set_date_timestamp,
       DATE_FORMAT(h.due_date, '%D %M %Y') AS due_date_DMY, 
       DATE_FORMAT(h.due_date, '%b %e, %Y') AS due_date_beY,
       UNIX_TIMESTAMP(h.due_date) AS due_date_timestamp, 
       IF(h.due_date<=DATE(NOW()), 1, 0) AS homework_due, 
       r1.total_issues, 
       IF(r2.total_returned IS NULL, 0, r2.total_returned) AS total_returned, 
       IF(h.due_date<=DATE(NOW()), r1.total_issues, IF(r2.total_returned IS NULL, 0, r2.total_returned)) AS waiting_review,
       h.resource_file
FROM tbl_homework h
INNER JOIN tbl_users u 
    ON u.uid = h.teacher_id
INNER JOIN (
    SELECT homework_id, COUNT(uid) AS total_issues 
    FROM tbl_homework_student_log
) r1 ON r1.homework_id = h.uid
LEFT JOIN (
    SELECT uid, homework_id, COUNT(uid) total_returned 
    FROM tbl_homework_student_log
    WHERE homework_completed = 1
) r2 ON r2.homework_id = h.uid 
LEFT JOIN (
    SELECT homework_id, COUNT(uid) waiting_review 
    FROM tbl_homework_student_log
    WHERE seen_by_issuer = 0
) r3 ON r3.homework_id = h.uid
WHERE h.teacher_id = ?
    AND h.set_date>=DATE_SUB(NOW(), INTERVAL 10 DAY) 
    AND h.homework_template = 0
ORDER BY h.class_id ASC, 
    h.set_date ASC

2 个答案:

答案 0 :(得分:1)

您并不真正需要子查询,更不用说其中三个用于获取您正在寻找的数据。我相信以下内容可以解决问题:

SELECT h.uid,h.class_id, h.homework_details, h.require_upload_return,
       CONCAT(u.surname, ', ', u.forename) AS teacher_name, 
       DATE_FORMAT(h.set_date, '%D %M %Y') AS set_date_DMY,
       DATE_FORMAT(h.set_date, '%b %e, %Y') AS set_date_beY,
       UNIX_TIMESTAMP(h.set_date) AS set_date_timestamp,
       DATE_FORMAT(h.due_date, '%D %M %Y') AS due_date_DMY, 
       DATE_FORMAT(h.due_date, '%b %e, %Y') AS due_date_beY,
       UNIX_TIMESTAMP(h.due_date) AS due_date_timestamp, 
       IF(h.due_date<=DATE(NOW()), 1, 0) AS homework_due, 
       COUNT(*) AS total_issues, 
       SUM(IF(l.homework_completed, 1, 0)) AS total_returned,
       SUM(IF(l.seen_by_issuer = 0, 1, 0)) AS waiting_review,
       h.resource_file
FROM tbl_homework h
    INNER JOIN tbl_users u ON u.uid = h.teacher_id
    INNER JOIN tbl_homework_student_log l ON h.uid = l.homework_id
WHERE h.teacher_id = ?
    AND h.set_date>=DATE_SUB(NOW(), INTERVAL 10 DAY) 
    AND h.homework_template = 0
GROUP BY h.uid
ORDER BY h.class_id ASC, 
    h.set_date ASC

答案 1 :(得分:1)

主要问题是您在子查询中缺少GROUP BY子句,因此您需要计算符合WHERE条款的表中的所有内容,而不是计算它们学生。此外,所有这些tbl_homework_student_log子查询可以合并为一个查询。

SELECT h.uid, h.class_id, h.homework_details, h.require_upload_return,
       CONCAT(u.surname, ', ', u.forename) AS teacher_name, 
       DATE_FORMAT(h.set_date, '%D %M %Y') AS set_date_DMY,
       DATE_FORMAT(h.set_date, '%b %e, %Y') AS set_date_beY,
       UNIX_TIMESTAMP(h.set_date) AS set_date_timestamp,
       DATE_FORMAT(h.due_date, '%D %M %Y') AS due_date_DMY, 
       DATE_FORMAT(h.due_date, '%b %e, %Y') AS due_date_beY,
       UNIX_TIMESTAMP(h.due_date) AS due_date_timestamp, 
       IF(h.due_date<=DATE(NOW()), 1, 0) AS homework_due, 
       r.total_issues, 
       IFNULL(r.total_returned, 0) AS total_returned, 
       IF(h.due_date<=DATE(NOW()), r.total_issues, IFNULL(r.waiting_review, 0)) AS waiting_review,
       h.resource_file
FROM tbl_homework h
INNER JOIN tbl_users u 
    ON u.uid = h.teacher_id
INNER JOIN (
     SELECT homework_id, COUNT(*) AS total_issues
            SUM(homework_completed = 1) AS total_returned,
            SUM(seen_by_issuer = 0) AS waiting_review
     FROM tbl_homework_student_log
     GROUP BY homework_id
) r ON r.homework_id = h.uid
WHERE h.teacher_id = ?
    AND h.set_date>=DATE_SUB(NOW(), INTERVAL 10 DAY) 
    AND h.homework_template = 0
ORDER BY h.class_id ASC, 
    h.set_date ASC