【问题标题】:adding and incrementing date and time (Postgresql)添加和递增日期和时间(Postgresql)
【发布时间】:2013-09-05 12:03:07
【问题描述】:

下表是用于显示媒体何时播放的表格。所以基本上它有一个开始时间(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 值作为开始并递归执行此操作直到结束(跟随位置)。

提前谢谢..

【问题讨论】:

  • 努力理解你想要什么。间隔的总和?
  • 基本上我想将'clip_length'字段添加到'start'字段中,并将其保存在'ends'字段的同一行中。然后在下一行。使用上一次歌曲以即将到来的歌曲的开始时间结束。
  • 旁注:如果这些是当地时间并且应用程序在具有 DST 的时区运行,那么您将在转换过程中遇到错误。
  • 嗯,这里显示的时间是格林威治标准时间..所以系统已经将其转换为格林威治标准时间......

标签: sql postgresql date time increment


【解决方案1】:

SQL Fiddle

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

【讨论】:

  • 嘿,我觉得我不太明白。当我执行它时,它会将所有值更改为 sum(clip_length) 的“结束”值和 sum(clip_length) -最后一个剪辑长度作为“开始”值。对于所有行,其值相同
【解决方案2】:

您的数据模型非常糟糕。您正在存储至少两条冗余信息。您需要startsfile_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 移动到单独的表中,该表仅存储一次,用于一系列段。根据自开始以来之前剪辑的长度总和,即时计算剪辑开始时间。

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

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

【讨论】:

  • :) ,遗憾的是我无法控制数据库(无法删除列)。不是设计,没有数据字典。它是一个第三方应用程序。我正在尝试为其开发一个 API。
  • 哦,Field_id 不是很相关。它的自动生成
【解决方案3】:
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 fiddle

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

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 fiddle demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-17
    • 2016-07-25
    相关资源
    最近更新 更多