以下查询正常工作
SELECT "employee"."id",
"employee"."created",
(SELECT SUM(minutes) FROM jobs_job AS job WHERE job.employee_id = employee.id AND job.job_date BETWEEN '2018-10-21' AND '2018-10-30')
FROM users_employee AS employee
INNER JOIN users_user AS users ON (employee.user_id = users.id)
WHERE NOT ("users"."status" = 'F')
GROUP BY
employee.id
我得到正确的数据(对于在JOB表中没有记录的人为NULL
但是,如果我将相同的查询重新构建为 LEFT OUTER JOIN
SELECT "employee"."id",
"employee"."created",
SUM(job.minutes) AS job_minutes
FROM users_employee AS employee
INNER JOIN users_user AS users ON (employee.user_id = users.id)
LEFT OUTER JOIN jobs_job AS job on employee.id = job.employee_id
WHERE NOT ("users"."status" = 'F') AND job.job_date BETWEEN '2018-10-21' AND '2018-10-30'
GROUP BY
employee.id
在原始查询中,我得到的是 112 行,而不是 142 行,并且仅存在作业表中的记录
答案 0 :(得分:1)
是因为这种咬伤:
Student oldest = studentList.pollLast();
您需要像这样将其移至LEFT JOIN:
AND job.job_date BETWEEN '2018-10-21' AND '2018-10-30'
答案 1 :(得分:1)
您需要在ON规则中使用其他条件,而不是where子句
LEFT OUTER JOIN jobs_job AS job on employee.id = job.employee_id
AND job.job_date BETWEEN '2018-10-21' AND '2018-10-30'
答案 2 :(得分:1)
您需要将 last 表上的条件移至on
子句。第二张表上的过滤保留在where
中:
SELECT "employee"."id",
"employee"."created",
SUM(job.minutes) AS job_minutes
FROM users_employee employee INNER JOIN
users_user users
ON employee.user_id = users.id LEFT OUTER JOIN
jobs_job job
ON employee.id = job.employee_id AND
job.job_date BETWEEN '2018-10-21' AND '2018-10-30'
WHERE "users"."status" <> 'F'
GROUP BY employee.id;
该逻辑以这种方式工作,因为左外部联接从NULL
的第二个表中产生JOIN
个值的结果。可以在NULL
子句中过滤掉这些WHERE
值。
答案 3 :(得分:1)
提供的所有答案将帮助您修复代码。我只想扩展一下为什么它们会起作用。
SQL引擎首先评估您的FROM
和JOIN
,然后将您的初始数据集存储到内存中。那时,因为您使用了LEFT OUTER JOIN
,所以您期望的所有行都仍然存在。
之后,它将应用您的WHERE
子句。在这种情况下,您的WHERE
子句包含job.job_date BETWEEN '2018-10-21' AND '2018-10-30'
,因此引擎会过滤掉所有不符合该条件的行。这实际上使LEFT JOIN
的结果与INNER JOIN
的结果完全相同。
最好的答案(已多次提出)是将过滤条件移至ON
子句。一种可行的替代方法是,在现有的IS NULL
子句中添加WHERE
可能性:
...
WHERE
NOT ("users"."status" = 'F')
AND
(
(job.job_date BETWEEN '2018-10-21' AND '2018-10-30')
OR
job.job_date IS NULL
)
尽管如此,使用JOIN
上的条件会更好,因为首先要将较少的记录拉入内存。