我正在尝试编写一个查询,该查询将返回未参加任何课程超过5个月的学生的列表。我认为我的逻辑正确,但是无法在SQL Plus中使用Datediff()。我想知道是否还有其他方法。
查询:
SELECT s.Reg_No, s.First_Name, s.Last_Name, s.Admission_Date
FROM Student s
INNER JOIN Enrolled_In e ON s.Reg_No = e.Reg_No
WHERE (s.Reg_No != e.Reg_No) AND (DATEDIFF(months, GETDATE(), s.Admission_Date) > 5);
Oracle具有months_between
function:
months_between
您也可以使用AND MONTHS_BETWEEN(sysdate, s.Admission_Date) > 5
:
add_months
function
[如果有的话,它仍然可以在该列上使用索引。
并且您可以使用间隔,但是由于月份长度不同,因此使用月份间隔进行加/减会引起问题。
虽然您的逻辑看起来不正确。首先,您需要将add_months
值与AND s.Admission_Date < ADD_MONTHS(sysdate, -5)
和reg_no
都进行比较,这两者不能同时为真。您还在查看=
,而不是!=
中的日期。
[您想查找最近五个月没有上过课的学生,因此您可以找到最新的上学并过滤掉这些,例如(猜测您有一个名为s.admission_date
的列,您需要检查):
enrolled_in
它将找到某个时候入学但最近五个月没有入学的学生。如果要包括从未入学的学生,可以使用外部联接:
enrolled_date
或者因为您没有从注册中报告任何数据,您可以将SELECT s.Reg_No, s.First_Name, s.Last_Name, s.Admission_Date
FROM Student s
INNER JOIN Enrolled_In e ON s.Reg_No = e.Reg_No
GROUP BY s.Reg_No, s.First_Name, s.Last_Name, s.Admission_Date
HAVING MAX(e.Enrolled_Date) < ADD_MONTHS(sysdate, -5)
与子查询一起使用以查找任何最近的课程:
SELECT s.Reg_No, s.First_Name, s.Last_Name, s.Admission_Date
FROM Student s
LEFT OUTER JOIN Enrolled_In e ON s.Reg_No = e.Reg_No
AND e.Enrolled_Date >= ADD_MONTHS(sysdate, -5)
GROUP BY s.Reg_No, s.First_Name, s.Last_Name, s.Admission_Date
HAVING COUNT(e.Enrolled_Date) = 0
找到在学生表中但不在登记表中的学生
您也可以使用not exists
查询-只需检查日期即可:
not exists
但是,正如您自己发现的那样,使用外部联接和空检查或计数也可以。
我认为您查询的逻辑不正确。如果您希望最近5个月内未注册的学生,可以通过使用获取上次注册日期的相关子查询来过滤students表来表述:
SELECT s.Reg_No, s.First_Name, s.Last_Name, s.Admission_Date
FROM Student s
WHERE NOT EXISTS (
SELECT null
FROM Enrolled_In e
WHERE e.Reg_No = s.Reg_No
AND e.Enrolled_Date >= ADD_MONTHS(sysdate, -5)
);