修改的
(根据后面评论中提供的说明进行修改:)
SELECT a.id
, a.date
, a.grade
, NULLIF(MAX(l.id) IS NOT NULL,0) AS leave
, IF(MAX(l.id) IS NULL,a.grade,1) AS fgrade
FROM student_attendance a
LEFT
JOIN leave_application l
ON l.uid = a.id
AND l.from <= a.date
AND l.to + INTERVAL 1 DAY > a.date
AND l.status = 'Approved'
GROUP BY a.id, a.date, a.grade
为了性能,您可能需要索引
... ON `student_attendance` (`id`, `date`, `grade`)
... ON `leave_application` (`uid`, `status`, `from`, `to`, `uid`)
您可以使用 EXPLAIN SELECT ... 来获取有关访问计划的信息。
8.8.1 使用解释优化查询 http://dev.mysql.com/doc/refman/5.5/en/using-explain.html
早些时候:
我认为这会返回指定的结果集。
SELECT a.id
, a.date
, a.grade
, l.id AS leave
, IF(l.id IS NULL,a.grade,1) AS fgrade
FROM student_attendance a
LEFT
JOIN leave_application l
ON l.uid = a.id
AND l.from <= a.date
AND l.to >= a.date
AND l.status = 1 /* approved */
JOIN 谓词匹配学生 ID,以及休假期间出勤日期的范围检查,以及批准的休假。
如果没有匹配(重叠)的休假行,则为 fgrade 分配来自等级列的值。否则,我们为 fgrade 分配 1。
根据对您的问题留下的评论,可以将作为 IF 函数中第三个参数的文字 1 替换为对来自 leave_application 的状态列的引用。如果学生获得休假但也获得了成绩,则添加成绩和休假状态可能会导致比您想要的值更高的值。1+1=2。
IF(l.id IS NULL,a.grade,l.status) AS fgrade
student_attendance 中的一行可能会匹配 leave_application 表中的多行。我们可以使用 GROUP BY 和聚合来解决这个问题......
SELECT a.id
, a.date
, a.grade
, MAX(l.id) AS leave
, IF(MAX(l.id) IS NULL,a.grade,1) AS fgrade
FROM student_attendance a
LEFT
JOIN leave_application l
ON l.uid = a.id
AND l.from <= a.date
AND l.to >= a.date
AND l.status = 1 /* approved */
GROUP BY a.id, a.date, a.grade
如果status
实际上是一个包含 的字符串'Approved'
,则可以调整查询。离开列的值可能不是 id。从示例数据中无法判断,因为 leave 的值与 id 和状态“已批准”的值 1 匹配。因此,该值实际上可能来自
l.status AS leave
NULLIF(l.id IS NOT NULL,0) AS leave
IF(l.id IS NOT NULL,1,NULL) AS leave
(l.id/l.id) AS leave
这些表达式中的任何一个都将给出示例数据中显示的结果。
同样,根据对您问题的评论中提供的其他信息...
SELECT a.id
, a.date
, a.grade
, NULLIF(MAX(l.id) IS NOT NULL,0) AS leave
, IF(MAX(l.id) IS NULL,a.grade,1) AS fgrade
FROM student_attendance a
LEFT
JOIN leave_application l
ON l.uid = a.id
AND l.from <= a.date
AND l.to >= a.date
AND l.status = 'Approved'
GROUP BY a.id, a.date, a.grade