Oracle GROUP BY类似的时间戳?

时间:2012-04-02 16:28:12

标签: sql oracle group-by

我有一个活动表,其结构如下:

id  prd_id  act_dt               grp
------------------------------------
1   1       2000-01-01 00:00:00
2   1       2000-01-01 00:00:01
3   1       2000-01-01 00:00:02
4   2       2000-01-01 00:00:00
5   2       2000-01-01 00:00:01
6   2       2000-01-01 01:00:00
7   2       2000-01-01 01:00:01
8   3       2000-01-01 00:00:00
9   3       2000-01-01 00:00:01
10  3       2000-01-01 02:00:00

我想按产品(prd_id)和活动日期(act_dt)拆分此活动表中的数据,并使用以下值更新组(grp)列每个组的序列。

踢球者是,我需要通过类似的时间戳进行分组,其中类似的意思是“所有记录的差异恰好为1秒”。换句话说,在一个组中,按日期排序的任何2条记录之间的差异恰好是1秒,并且第一条记录和最后一条记录之间的差异可以是任何时间量,只要所有中间记录都是1秒开。

对于示例数据,组将是:

id  prd_id  act_dt               grp
------------------------------------
1   1       2000-01-01 00:00:00  1
2   1       2000-01-01 00:00:01  1
3   1       2000-01-01 00:00:02  1
4   2       2000-01-01 00:00:00  2
5   2       2000-01-01 00:00:01  2
6   2       2000-01-01 01:00:00  3
7   2       2000-01-01 01:00:01  3
8   3       2000-01-01 00:00:00  4
9   3       2000-01-01 00:00:01  4
10  3       2000-01-01 02:00:00  5

我会用什么方法来实现这个目标?

如果这会影响用于解决问题的方法,那么表的大小约为2000万行。

1 个答案:

答案 0 :(得分:2)

我不是Oracle的头衔,所以我猜测一行的最佳选择:

    (CAST('2010-01-01' AS DATETIME) - act_dt) * 24 * 60 * 60      AS time_id,

这只需要是“从[aDateConstant]到act_dt”的秒数。结果可能是负面的。将act_dt转换为INT,只需要几秒钟即可。其余的应该可以正常工作。

WITH
  sequenced_data
AS
(
  SELECT
    ROW_NUMBER() OVER (PARTITION BY prd_id  ORDER BY act_dt)      AS sequence_id,
    (CAST('2010-01-01' AS DATETIME) - act_dt) * 24 * 60 * 60      AS time_id,
    *
  FROM
    yourTable
)
SELECT
  DENSE_RANK() OVER (PARTITION BY prd_id ORDER BY time_id - sequence_id) AS group_id,
  *
FROM
  sequenced_data 

示例数据:

 sequence_id | time_id | t-s | group_id
-------------+---------+-----+----------
      1      |   1     |  0  |    1
      2      |   2     |  0  |    1
      3      |   3     |  0  |    1
      4      |   8     |  4  |    2
      5      |   9     |  4  |    2
      6      |   12    |  6  |    3
      7      |   14    |  7  |    4
      8      |   15    |  7  |    4


注意: 假设 多条记录具有相同的时间。如果存在,则需要先将其过滤掉。可能只是在前面的CTE中使用GROUP BY。