【问题标题】:Get biggest difference in successive timestamps with additional constraint?通过附加约束获得连续时间戳的最大差异?
【发布时间】:2017-07-20 14:25:22
【问题描述】:

我有一张桌子items,它代表移动的物品。其中,该表具有 PK name、时间戳 creation_time(包含创建条目的时间)和字符串 type(可以是 startmoveend 和 @ 987654329@ 条目介于 startend 之间。

表格的一部分可能如下所示:

name creation_time       type
_________________________________
i1   2017-03-01 10:00:01 start
i1   2017-03-01 10:00:02 move
i1   2017-03-01 10:00:08 move
i1   2017-03-01 10:00:10 end
i1   2017-03-01 10:00:31 start
i1   2017-03-01 10:00:33 move
i1   2017-03-01 10:00:37 end

我想要得到的是连续时间戳的最大差异,其中第二个时间戳的类型不是start(我不关心endstart 之间的时间)。

基于this SO question,我提供了以下查询,该查询尚未考虑条目的类型:

select name, creation, next_creation, (next_creation-creation) difference from (
  select name, creation, (
    select min(creation) from items i2
    where i2.name=i.name
    and i2.creation > i.creation
  ) as next_creation
  from items i
)
where (next_creation-creation) is not null
order by difference desc

我的问题是我现在不知道如何正确过滤该类型。据我了解,我必须从最里面的查询中获取类型,因为我关心第二个条目的类型,然后将 and type<>'start' 添加到最外面的查询的 where 子句中 - 但我不能得到两个子查询中的值,对吧?

编辑:我期望的结果如下所示:

name creation            next_creation        difference action
i1   2017-03-01 10:00:02 2017-03-01 10:00:08  6s         move
i1   2017-03-01 10:00:33 2017-03-01 10:00:37  4s         end
[...]

如您所见,第一个 end 和第二个 start 之间的时间没有条目,这就是要通过过滤类型来完成的。

例如,第一个和最后一个条目之间的时间也没有条目,因为我想要连续条目之间的差异。

【问题讨论】:

  • 请告诉我们查询的最终结果应该是什么样子。
  • 您需要每个名称值的最大差异吗?

标签: sql oracle


【解决方案1】:

在编辑之前回答问题:

使用LAG analytic function

SELECT name,
       MAX( time_difference ) AS max_time_difference
FROM   (
  SELECT name,
         type,
         creation_time
           - LAG( creation_time ) OVER ( PARTITION BY name ORDER BY creation_time )
           AS time_difference
  FROM   items
)
WHERE type != 'start'
GROUP BY name;

更新

为每组开始/结束项目获取它(这似乎是您预期的输出显示 - 因为它有多行):

SELECT name,
       creation_time,
       next_creation_time,
       next_creation_time - creation_time AS difference,
       type
FROM   (
  SELECT i.*,
         ROW_NUMBER() OVER (
           PARTITION BY name, start_group
           ORDER BY next_creation_time - creation_time DESC, creation_time ASC
         ) AS rn
  FROM   (
    SELECT name,
           type,
           creation_time,
           LEAD( creation_time ) OVER ( PARTITION BY name ORDER BY creation_time )
             AS next_creation_time,
           SUM( CASE type WHEN 'start' THEN 1 END )
             OVER( PARTITION BY name ORDER BY creation_time )
             AS start_group
    FROM   items
  ) i
  WHERE type != 'end'
)
WHERE rn = 1;

【讨论】:

  • 谢谢!该函数正是我所搜索的,并且比我构建的查询要快。
【解决方案2】:

如果您需要每个名称值的最大差异,那么应该可以:

SELECT i1.NAME, MAX(i2.creation_time - i1.creation_time) difference
FROM items i1
INNER JOIN items i2 ON i1.name = i2.name AND i1.creation_time <= i2.creation_time
WHERE 'start' NOT IN (i1.type, i2.type)
GROUP BY i1.name;

【讨论】:

    【解决方案3】:

    根据我的理解。这必须是子查询中包含的列“TYPE”,可用作内联视图中的过滤器。希望对您有所帮助。

    SELECT name,
      creation,
      next_creation,
      (next_creation-creation) difference
    FROM
      (SELECT name,
        creation,
        (SELECT MIN(creation)
        FROM items i2
        WHERE i2.name   =i.name
        AND I2.CREATION > I.CREATION
        ) AS NEXT_CREATION,
        type
      FROM items i
      )
    WHERE (NEXT_CREATION-CREATION) IS NOT NULL
    and type                       <> 'start'
    ORDER BY difference DESC;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-04
      • 1970-01-01
      • 2019-05-06
      • 2020-10-21
      • 2017-03-13
      • 1970-01-01
      • 2021-11-13
      • 1970-01-01
      相关资源
      最近更新 更多