datediff()的替代方法是什么来查找日期差异?

tzdcorbm  于 2021-07-26  发布在  Java
关注(0)|答案(2)|浏览(348)

我试图写一个查询,返回超过5个月没有参加任何课程的学生名单。我想我的逻辑是对的,但是我不能在SQLPlus中使用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);
daolsyd0

daolsyd01#

甲骨文有一个 months_between 功能:

AND MONTHS_BETWEEN(sysdate, s.Admission_Date) > 5

你也可以用 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 使用子查询查找最近的课程:

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)
);

查找学生表中存在但未注册的学生
你可以用 not exists 也可以查询-只需进行日期检查:

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
);

不过,使用外部连接和空检查或计数也很有效,这是您自己想出来的。

axzmvihb

axzmvihb2#

我认为你的询问逻辑是不正确的。如果您想要在过去5个月内没有注册的学生,可以使用获取最后注册日期的相关子查询筛选学生表:

select s.*
from students s
where 
    (
        select max(e.admission_date)
        from enrolled_in e
        where e.reg_no = e.reg_no
    ) < sysdate - interval '5' month
    or not exists (
        select 1
        from enrolled_in e
        where e.reg_no = e.reg_no
    )

相关问题