Oracle 中的 LAG 函数

Posted

技术标签:

【中文标题】Oracle 中的 LAG 函数【英文标题】:LAG Function in Oracle 【发布时间】:2017-05-24 09:18:25 【问题描述】:

我有一个包含Create_date(DataType=Date) 列的表(事件)。 我想从以前的记录中获得天数或小时数的差异。就像下面的截图一样。

从第二个记录 Create_Date 我想减去第一个 Create_Date 和从第三个创建日期到第二个等等。我在 Oracle 中使用 LAG 函数,但不确定它是如何计算的。谁能帮我解决这个问题。

incident.create_date - lag(incident.create_date,1) OVER (ORDER BY incident.create_date) AS CREATEDATE_DIFF,

RN 1 我们有 Create_date (05/01/017 10:40:17 AM

【问题讨论】:

【参考方案1】:

Oracle 中的日期差异以天数计算。如果差值小于一天,则返回的值将小于 1。

如果要将其转换为小时,则必须将结果乘以 24,分钟乘以 24*60,秒乘以 24*60*60。

例如:

select sysdate - trunc(sysdate) diff_in_days,
       (sysdate - trunc(sysdate))*24 diff_in_hours,
       (sysdate - trunc(sysdate))*24*60 diff_in_mins,
       (sysdate - trunc(sysdate))*24*60*60 diff_in_secs
from   dual;

DIFF_IN_DAYS DIFF_IN_HOURS DIFF_IN_MINS DIFF_IN_SECS
------------ ------------- ------------ ------------
0.4342245370 10.4213888888 625.28333333        37517

然后,您可能希望应用 ROUND(或者可能是 TRUNC/CEIL),具体取决于您希望输出的外观(例如,到 2 d.p.、到最近的分钟等)。

【讨论】:

感谢您的回复,但是如何在不使用任何 LAG 函数的情况下对 FirstDate 进行第二次创建减号。我附上了其计算差异但不确定其计算方式的屏幕截图。例如。第二条记录(05/01/017 10:49:37)- 05/01/017 上午 10:40:17(第一条记录)这意味着大约 0 小时 55 分 34 秒,但它显示了一些东西(0.001388888)。即使我将其 0.0 * 24 (IN Days) 舍入。 您将在完成所有计算后进行四舍五入(如果您提前四舍五入,您的计算会变得不那么准确!)。因此,round((<date2> - <date1>)*24*60, 2) 将获取您的两个日期,找出差异,将其乘以 24 和 60,然后将其四舍五入到小数点后两位。 如果你需要0天3小时29分10秒的答案,我建议你看看MT0的答案,顺便说一句。【参考方案2】:

如果您从另一个日期中减去一个日期,您将得到天数(或其分数)的差异。

您可以使用间隔获取此日期/小时/分钟/秒:

SELECT EXTRACT( DAY    FROM createdate_diff ) AS days,
       EXTRACT( HOUR   FROM createdate_diff ) AS hours,
       EXTRACT( MINUTE FROM createdate_diff ) AS minutes,
       EXTRACT( SECOND FROM createdate_diff ) AS seconds,
       createdate_diff
FROM   (
  SELECT NUMTODSINTERVAL(
           create_date - lag(create_date) OVER (ORDER BY create_date),
           'DAY'
         ) AS CREATEDATE_DIFF
  FROM   incident
);

或者您可以手动执行相同的计算:

SELECT TRUNC( createdate_diff ) AS days,
       TRUNC( MOD( createdate_diff * 24, 24 ) ) AS hours,
       TRUNC( MOD( createdate_diff * 24 * 60, 60 ) ) AS minutes,
       MOD( createdate_diff * 24 * 60 * 60, 60 ) AS seconds,
       createdate_diff
FROM   (
  SELECT create_date - lag(create_date) OVER (ORDER BY create_date)
           AS CREATEDATE_DIFF
  FROM   incident
);

【讨论】:

澄清一下,此解决方案将产生按天、小时、分钟和秒划分的差异,而不是作为具有单个单位的数字(即 0 天、1 小时、53 分钟和 30 秒) , vs 6810 秒或 113.5 分钟)。我不确定这正是 OP 所追求的,但从他们提供的信息中不一定清楚! @Boneist 从OP's comment 看来,他们似乎想要(即使他们的示例中的输入值不正确)类似“0 小时 55 分 34 秒”的输出。 这与他们原始帖子中的days OR hours 不符!我并不是说这是一个错误的答案;我只是想为 OP 澄清一下,因为这可能正是他们想要的。 如果您愿意,也可以使用 CAST(create_date as TIMESTAMP) - LAG(create_date) OVER (ORDER BY create_date) 代替 NUMTODSINTERVAL【参考方案3】:

使用

......
(incident.create_date - 
 lag(incident.create_date,1) OVER (ORDER BY incident.create_date))
 *24*60
 AS CREATEDATE_DIFF_IN_MINS,.....

minutes 中获取输出,该输出适合您的样本数据。或者进一步乘以60 得到seconds 的输出。

【讨论】:

谢谢,但我仍然没有得到,因为我正在使用您发布的内容。(incident.create_date - lag(incident.create_date,1) OVER (ORDER BY event.create_date))*24 *60 AS CREATEDATE_DIFF, Second Date(05/01/017 10:58:54 AM)-FirstDate(04/01/017 01:53:04 PM) 它得到 1.86666 差异大约是 21 小时 5 分钟,但结果我'使用上述代码 24*60 后,我得到 1.866。请帮助我 不确定你的意思。如果您想在几分钟内获得输出,我只是建议将您已经存在的结果乘以 24*60。您当前的输出是什么,您的期望是什么?

以上是关于Oracle 中的 LAG 函数的主要内容,如果未能解决你的问题,请参考以下文章

oracle 中的 Lead & LAG 聚合

Oracle/SQLServer 中的分析函数高级教程 [关闭]

MYSQL lag() 和lead()函数使用介绍

lag与lead函数 oracle_11g

ORACLE 偏移分析函数 lag()与lead() 用法

ORACLE 偏移分析函数 lag()与lead() 用法