4

下面是一个表格,用于显示媒体何时播放。所以基本上它有一个开始时间(starts),轨道的长度(clip_length),结束时间(ends= starts + clip_length),最后是轨道的位置。

|starts              | ends                 |position   |file_id| clip_length
|2013-08-30 22:00:00 | 2013-08-30 22:03:08  |0          |16     |00:03:08.081768
|2013-08-30 22:03:08 | 2013-08-30 22:06:33  |1          |17     |00:03:25.436485
|2013-08-30 22:06:33 | 2013-08-30 22:09:07  |2          |7      |00:02:33.79968
|2013-08-30 22:09:07 | 2013-08-30 22:12:21  |3          |3      |00:03:14.020273
|2013-08-30 22:12:21 | 2013-08-30 22:15:31  |4          |8      |00:03:10.466689

我想做的是添加一条记录,例如position =2,如下所示。我已经能够增加职位,但问题在于时间都一团糟。

|starts              | ends                 |position   |file_id|clip_length
|2013-08-30 22:00:00 | 2013-08-30 22:03:08  |0          |16     |00:03:08.081768
|2013-08-30 22:03:08 | 2013-08-30 22:06:33  |1          |17     |00:03:25.436485
|2013-08-30 22:06:33 | 2013-08-30 22:09:07  |2          |7      |00:02:33.79968
|2013-08-30 22:06:33 | 2013-08-30 22:11:03  |3          |1      |00:04:30.006958
|2013-08-30 22:09:07 | 2013-08-30 22:12:21  |4          |3      |00:03:14.020273
|2013-08-30 22:12:21 | 2013-08-30 22:15:31  |5          |8      |00:03:10.466689

因此可以使用第一个开始时间.. 作为点 00,并添加clip_length到第一个starts并保存在ends, 中。然后对于第二个使用第一个ends值作为开始并递归执行此操作直到结束(跟随位置)。

提前致谢..

4

3 回答 3

4

SQL小提琴

update clip c
set
    starts = s.starts,
    ends = s.ends
from (
    select
        starts,
        starts + clip_length as ends,
        file_id,
        position
    from (
        select
            '2013-08-30 22:00:00'::timestamp
            + sum(clip_length) over(order by position)
            - clip_length as starts,
            clip_length,
            file_id,
            position
        from clip
    ) s
) s
where c.file_id = s.file_id
于 2013-09-02T12:05:24.690 回答
3

您的数据模型非常无聊。您正在存储至少两条冗余信息。您需要startsand和, orfile_id中的任何一个;它们可以相互计算。clip_lengthendsposition

现在您正在存储冗余数据,这会产生您现在遇到的问题,即数据内部不一致,它自身内部存在冲突。

在这种情况下,它听起来像是position受信任的,而其他的则不是。这是我要做的:

SELECT 
  (SELECT min(starts) FROM Sometable)
    + COALESCE(
       sum(clip_length) OVER all_rows_but_last,
       INTERVAL '0' second
    )
  AS starts,
  (SELECT min(starts) FROM Sometable)
    + COALESCE(
       sum(clip_length) OVER all_rows_but_last,
       INTERVAL '0' second
    ) + clip_length
  AS ends, 
  position, 
  clip_length
FROM Sometable
WINDOW all_rows_but_last AS (ORDER BY position ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING);

见:http ://sqlfiddle.com/#!12/ca5fa/1

这里的原则是找到最低的开始 - 已知有效的开始 - 并忽略以下结束和开始,因为它们是多余和无用的。相反,将先前持续时间的运行总计添加为开始,并将相同的运行总计加上当前间隔作为结束。

您会注意到这不是更新。那是因为我认为您实际上应该:

  • 更改position为浮点值或大整数,以便在插入条目时无需重新编号。如果你把东西放在中间12给它位置0.5。或以 等开头1000020000以便您可以插入15000.

  • 完全摆脱ends柱子。从starts+计算clip_length

  • 移动starts到一个单独的表,它只存储一次,用于一系列段。从开始以来先前剪辑的长度总和即时计算剪辑开始时间。

  • 将当前表重新定义为上述两个表的视图。

这对你的数据以及你如何使用它做出了很多猜测,但你对你在做什么并没有说太多。

于 2013-09-02T12:11:46.267 回答
1
with cte as (
    select
        '2013-08-30 22:00:00'::timestamp
         + sum(clip_length) over(order by position) as ends,
         file_id
    from clip
)
update clip as cl set
    starts = c.ends - cl.clip_length,
    ends = c.ends
from cte as c
where cl.file_id = c.file_id;

=> sql 小提琴

实际上,您可以在表中完全没有开始和结束时间。您可以从表中删除此列并创建如下函数:

create or replace function clip_layout(_starts timestamp)
returns table(
    starts timestamp, ends timestamp,
    "position" int, file_id int,clip_length interval
)
as
$$
with cte as (
    select
        _starts + sum(clip_length) over(order by position) as ends,
        file_id, clip_length, position
    from clip
)
select
    ends - clip_length as starts,
    ends, position,
    file_id, clip_length
from cte
$$
language sql;

因此,您可以随时查看开始/结束时间:

select * from clip_layout('2013-08-30 22:00:00'::timestamp)

=> sql 小提琴演示

于 2013-09-02T14:29:32.920 回答