[英]Mysql join two table based on between dates
我在mysql数据库中有一个学生出勤视图,如下所示
id date grade
239 01/09/2012 1
239 02/09/2012 0
239 04/09/2012 0
239 05/09/2012 1
239 07/09/2012 0
239 25/09/2012 0
239 26/09/2012 0
而且我在数据库中还有一个请假申请表,如下所示。 其中批准= 1,拒绝= 0。
id uid from to status
1 239 04/09/2012 07/09/2012 approved
2 239 26/09/2012 26/09/2012 rejected
现在我想创建一个查询来显示批准的假期和学生的最终成绩,如下所示
id date grade leave Fgrade
239 01/09/2012 1 1
239 02/09/2012 0 0
239 04/09/2012 0 1 1
239 05/09/2012 1 1 1
239 07/09/2012 0 1 1
239 25/09/2012 0 0
239 26/09/2012 0 0
请告诉我如何获得此结果。
改性
(基于后面评论中的说明进行的修改:)
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中的status列。 如果学生被授予休假,但同时也获得了成绩,则添加成绩和休假状态可能会获得比您想要的更高的价值。 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。 从示例数据中无法得知,因为请假的值与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
尝试
SELECT a.id, a.date, a.grade,
CASE WHEN l.status = 'approved' THEN 1 END `leave`,
CASE WHEN l.status = 'approved' THEN 1 ELSE a.grade END fgrade
FROM attendance a LEFT JOIN `leave` l
ON a.id = l.uid
AND a.date BETWEEN l.from AND l.to
输出:
| ID | DATE | GRADE | LEAVE | FGRADE | ---------------------------------------------- | 239 | 2012-09-01 | 1 | (null) | 1 | | 239 | 2012-09-02 | 0 | (null) | 0 | | 239 | 2012-09-04 | 0 | 1 | 1 | | 239 | 2012-09-05 | 1 | 1 | 1 | | 239 | 2012-09-07 | 0 | 1 | 1 | | 239 | 2012-09-25 | 0 | (null) | 0 | | 239 | 2012-09-26 | 0 | (null) | 0 |
这是SQLFiddle演示
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.