【问题标题】:Derivative / time difference for time series data in SQLSQL中时间序列数据的导数/时间差
【发布时间】:2021-08-06 10:41:15
【问题描述】:

我正在查询一个请求数据集,并希望在服务请求之间获得“正常运行时间”。这篇文章Discrete Derivative in SQL 几乎就是我所追求的。但是,我正在处理日期时间数据,我不相信我可以假设工作订单将按时间顺序排序。另外,我对每个请求都有特定的位置。

Request Location RequestDate CompleteDate
R-001 a 1/1/2020 1/5/2020
R-002 a 3/17/2020 3/20/2020
R-004 b 2/27/2020 3/1/2020
R-003 b 4/22/2020 4/23/2020
R-005 a 7/3/2020 7/7/2020

我确实看到了SQL DATEDIFF() 函数。 以下是对引用帖子中顶级答案的轻微修改。

Select a.RequestDate as StartTime
     , b.CompleteDate as EndTime
     , DATEDIFF(b.RequestDate-a.CompleteDate) as TimeChange
FROM YourTable a 
Left outer Join YourTable b ON b.time>a.time
Left outer Join YourTable c ON c.time<b.time AND c.time > a.time
Where c.time is null
Order By a.RequestDate

另外,我有点掌握两次别名同一张表但不完全。我也不明白外部连接。 最终,我想要新的专栏……如果这样可以简化问题,我可以提前做出假设或按请求日期排序。

Request Location RequestDate CompleteDate Up-Time
R-001 a 1/1/2020 1/5/2020 null
R-002 a 3/17/2020 3/20/2020 72
R-004 b 2/27/2020 3/1/2020 null
R-003 b 4/22/2020 4/23/2020 52
R-005 a 7/3/2020 7/7/2020 105

我希望它与原始帖子没有太大不同,其中按位置分组并按请求日期排序。

【问题讨论】:

  • 您能否假设特定请求的 CompleteDate 早于该位置的下一个(按时间顺序)RequestDate? IE 一个特定位置可以同时有两张有效的票吗?
  • 时间戳在哪里?
  • 在您找到的帖子中,尝试阅读其他一些建议,尤其是包含LAG 窗口函数的建议。你可能会觉得这很有用。这是一种更直接的方式来使用前一行中的值,就像您似乎需要的那样,而不使用 JOIN
  • 另请注意:您将根据数据中的日期/时间或其他标准进行排序。如果您的数据不包含此排序的足够详细信息,您希望如何识别计算正常运行时间差异的行?您还可以使用窗口函数计算运行总和。

标签: sql postgresql


【解决方案1】:

这使用 LAG 窗口函数来分别执行每个位置的此 RequestDate 和上一个 CompleteDate 之间的差异(以天为单位),按 RequestDate 排序(这里有一些假设)。

CREATE TABLE log (
    Request      VARCHAR(30)
  , Location     VARCHAR(10)
  , RequestDate  date
  , CompleteDate date
);

INSERT INTO log VALUES 
  ('R-001', 'a',  '2020-1-1',    '2020-1-5' )
, ('R-002', 'a',  '2020-3-17',   '2020-3-20')
, ('R-004', 'b',  '2020-2-27',   '2020-3-1' )
, ('R-003', 'b',  '2020-4-22',   '2020-4-23')
, ('R-005', 'a',  '2020-7-3',    '2020-7-7' )
;

查询:

SELECT log.*
     , LAG(CompleteDate) OVER (PARTITION BY Location ORDER BY RequestDate) AS prev_date
     , RequestDate - LAG(CompleteDate) OVER (PARTITION BY Location ORDER BY RequestDate) AS diff
  FROM log
 ORDER BY Location, RequestDate 
;

结果:

Working test case

用于解决字符串到日期转换问题的附加 SQL (PostgreSQL):

WITH logs AS (
        SELECT Request, Location
             , TO_DATE(RequestDate, 'MM/DD/YYYY')  AS RequestDate
             , TO_DATE(CompleteDate, 'MM/DD/YYYY') AS CompleteDate
          FROM log
     )
SELECT log.*
     , LAG(CompleteDate) OVER (PARTITION BY Location ORDER BY RequestDate) AS prev_date
     , RequestDate - LAG(CompleteDate) OVER (PARTITION BY Location ORDER BY RequestDate) AS diff
  FROM logs AS log
 ORDER BY Location, RequestDate 
;

The updated working test case

【讨论】:

  • 谢谢,正如@alexherm 所说,我将如何将其转换为使用我当前的字符串格式。我想我可以用一个包装它们: SELECT CONVERT(VARCHAR(10), log.RequestDate, 101) FROM log;
  • @AKA_Tom 当然。您甚至可以在之前的 CTE 术语(WITH 子句)中执行此操作,并保留上述对日期类型进行操作的表达式。有时最好将问题分开。如何将字符串转换为日期是一个问题。如何处理衍生逻辑是另一回事。注意:您最初的问题没有提供太多 SQL 详细信息,例如确切的表和列类型,以及用于提供数据的插入语句。将我的测试用例视为一个很好的示例,以及问题应包含的细节类型。
  • @AKA_Tom 我添加了一个额外的查询来解决转换问题。没有必要这样做。但它清晰易懂。
猜你喜欢
  • 2018-10-24
  • 2020-08-11
  • 2021-05-31
  • 2015-12-06
  • 2015-07-06
  • 1970-01-01
  • 1970-01-01
  • 2019-05-20
  • 1970-01-01
相关资源
最近更新 更多