简体   繁体   English

MySQL左连接子查询null连接

[英]MySQL left join subquery null join

Ok, so I have a fairly detailed SQL query, I have 2 tables, the first table contains homework data. 好的,所以我有一个相当详细的SQL查询,我有2个表,第一个表包含作业数据。 The second table contains a record for each student in a class the homework is set for. 第二张表包含为该家庭作业设置的班级中每个学生的记录。

I want to count some data on the second table, where certain conditions are met, for example, how many students the homework was issued to, count how many students have returned homework, and count how many homeworks have been reviewed by the teacher. 我想在满足某些条件的第二张表上统计一些数据,例如,向多少学生发放了家庭作业,计算了多少学生归还了作业,还计算了老师复习了多少作业。

I'll post my query at the bottom of this post. 我将在本文的底部发布我的查询。

I'm using a subquery on 2 left joins. 我在2个左联接上使用子查询。 The subquery looks like this: 子查询如下所示:

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

In the example above, the student log table contains an index homework_id which links back to the master homework table's unique index h.uid . 在上面的示例中,学生日志表包含一个索引homework_id ,该索引链接回到主作业表的唯一索引h.uid

My problem is occuring when this scenario is valid: 这种情况有效时发生我的问题:

1) If COUNT(uid) equals 0, homework_id is NULL . 1)如果COUNT(uid)等于0,则homework_id为NULL

2) The query produces the following result 2)查询产生以下结果

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

My joins failing with the following error message: 我的联接失败,并显示以下错误消息:

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

I don't know how to solve this issue. 我不知道如何解决这个问题。 I initally had my subquery in the SELECT clause, but I want it in the LEFT JOINs. 我最初在SELECT子句中有我的子查询,但是我想在LEFT JOINs中有它。

My question is how can I make sure that r2.homework_id is never null? 我的问题是如何确保r2.homework_id永远不会为null? I've tried the following: 我尝试了以下方法:

  • Removed the COUNT() function from the join subqueries and moved them to the main select clause - Doesn't work as expected 从联接子查询中删除了COUNT()函数,并将其移至主选择子句-不能按预期工作
  • Moved the where clause in each join subquery to its associated ON clause - Doesn't work 将每个联接子查询中的where子句移至与其关联的ON子句-不起作用
  • Tried adding AND r2.homework_id IS NOT NULL to the respective ON clause - Doesn't work 尝试在各自的ON子句中添加AND r2.homework_id IS NOT NULL不起作用
  • Tried adding AND COUNT(uid)>0 to the WHERE clause in the join subquery - Doesn't work 尝试在连接子查询的WHERE子句中添加AND COUNT(uid)>0不起作用

I'm all out of ideas. 我全都没主意了。

Here's my whole query: 这是我的整个查询:

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

You don't really need sub-queries, much less three of them to get the data you're looking for. 您实际上并不需要子查询,只需更少的三个子查询即可获取所需的数据。 I believe the following will do the trick: 我相信以下将解决问题:

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

The main problem is that you're missing GROUP BY clauses in your subqueries, so you're counting everything in the table that meets the WHERE clauses, not counting them per-student. 主要问题是您的子查询中缺少GROUP BY子句,因此您要对表中符合WHERE子句的所有内容进行计数,而不是按学生对它们进行计数。 Also, all those tbl_homework_student_log subqueries can be combined into a single query. 同样,所有这些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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM