Datediff() 查找日期差异的替代方法是啥?

Posted

技术标签:

【中文标题】Datediff() 查找日期差异的替代方法是啥?【英文标题】:What is the alternate of Datediff() to find the date difference?Datediff() 查找日期差异的替代方法是什么? 【发布时间】:2020-06-06 08:09:03 【问题描述】:

我正在尝试编写一个查询,该查询返回超过 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);

【问题讨论】:

【参考方案1】:

Oracle 有一个months_between function:

AND MONTHS_BETWEEN(sysdate, s.Admission_Date) > 5

您也可以使用add_months function:

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

使用外连接和空值检查或计数也可以,正如您自己发现的那样。

【讨论】:

谢谢你的详细解释,亚历克斯!实际上,查询有两个条件;首先是找到在学生表中但不在已注册表中的学生,其次是按 5 个月的差异过滤结果。在您的帮助下,我能够通过使用左连接来查找空列和后半部分来解决第一个条件。干杯!【参考方案2】:

我认为你的查询逻辑不对。如果您想要过去 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
    )

【讨论】:

感谢您的回复!实际上,查询有两个条件;首先是找到在学生表中但不在已注册表中的学生,其次是按 5 个月的差异过滤结果。我通过使用左连接来查找空列解决了第一个条件,而后者通过使用 add_months() 来解决。

以上是关于Datediff() 查找日期差异的替代方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

DATEDIFF 按创建日期划分范围,利用外部日期按月计算年龄历史

Pyspark:两个日期之间的差异(Cast TimestampType,Datediff)

Javascript和datediff mysql中日期之间的日期差异不相等

来自两个表的两个最大日期时间值的 Datediff,并根据差异更新第三个表

sql数据库中的datediff函数是啥意思

PowerBI:根据 DATEDIFF 上的条件正确聚合度量