Postgresql - 获取相对于给定日期时间值的最接近的datetime行

时间:2013-05-01 16:01:28

标签: postgresql datetime

我有一个带有唯一日期时间字段的postgres表。 我想使用/创建一个函数,该函数将日期时间值作为参数,并返回与传递的日期时间值相关(但不相等)的最近日期时间的行ID。第二个参数可以在之前指定,在之后指定传递的值。

理想情况下,本机datetime functions的某些组合可以处理此要求。否则它必须是自定义功能。

问题:在一组行上查询相对日期时间的方法是什么?

6 个答案:

答案 0 :(得分:3)

select id, passed_ts - ts_column difference
from t
where
    passed_ts > ts_column and positive_interval
    or
    passed_ts < ts_column and not positive_interval
order by abs(extract(epoch from passed_ts - ts_column))
limit 1

passed_ts是时间戳参数,positive_interval是布尔参数。如果为true,则只有时间戳列低于传递时间戳的行。如果为反,则为假。

答案 1 :(得分:1)

简单地使用 - 。

假设您有一个包含Key,Attr和T属性的表(带或不带时区的时间戳):

 you can search with

 select min(T - TimeValue) from Table where (T - TimeValue) > 0;

这将给你带来的主要区别。您可以将此值与对同一表的连接组合以获得您感兴趣的元组:

 select * from (select *, T - TimeValue as diff from Table) as T1 NATURAL JOIN
               ( select min(T - TimeValue) as diff from Table where (T - TimeValue) > 0) as T2;

应该这样做

- DMG

答案 2 :(得分:1)

-- test rig
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;

CREATE TABLE lutser
        ( dt timestamp NOT NULL PRIMARY KEY
        );
-- populate it
INSERT INTO lutser(dt)
SELECT gs
FROM generate_series('2013-04-30', '2013-05-01', '1 min'::interval) gs
        ;
DELETE FROM lutser WHERE random() < 0.9;

-

-- The query:
WITH xyz AS (
        SELECT dt AS hh
        , LAG (dt) OVER (ORDER by dt ) AS ll
        FROM lutser
        )
SELECT  *
FROM xyz bb
WHERE '2013-04-30 12:00' BETWEEN bb.ll AND bb.hh
        ;

结果:

NOTICE:  drop cascades to table tmp.lutser
DROP SCHEMA
CREATE SCHEMA
SET
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "lutser_pkey" for table "lutser"
CREATE TABLE
INSERT 0 1441
DELETE 1288
         hh          |         ll          
---------------------+---------------------
 2013-04-30 12:02:00 | 2013-04-30 11:50:00
(1 row)

将它包装成一个函数留作读者的练习

更新:这是第二个使用夹心 - 不存在 - 技巧(TM):

SELECT lo.dt AS ll
FROM lutser lo
JOIN lutser hi ON hi.dt > lo.dt
        AND NOT EXISTS (
        SELECT * FROM lutser nx
        WHERE nx.dt < hi.dt
        AND nx.dt > lo.dt
        )
WHERE '2013-04-30 12:00' BETWEEN lo.dt AND hi.dt
        ;

答案 3 :(得分:1)

您希望select语句的第一行按降序(或升序)顺序生成给定日期时间下方(或上方)的所有行。

函数体的伪代码:

SELECT id
FROM table
WHERE IF(@above, datecol < @param, datecol > @param)
ORDER BY IF (@above. datecol ASC, datecol DESC)
LIMIT 1

然而,这不起作用:人们无法调整排序方向。

第二个想法是做两个查询,然后选择:

SELECT *
FROM (
    (
    SELECT 'below' AS dir, id
    FROM table
    WHERE datecol < @param
    ORDER BY datecol DESC
    LIMIT 1
    ) UNION (
    SELECT 'above' AS dir, id
    FROM table
    WHERE datecol > @param
    ORDER BY datecol ASC
    LIMIT 1)
 ) AS t
 WHERE dir = @dir

对于datetime列上的索引,这应该非常快。

答案 4 :(得分:0)

您必须使用where条件将表连接到自身,以查找基表行的datetime和连接表行的datetime之间的最小非零(负或正)间隔。在该日期时间列上有一个索引会很好。

P.S。您还可以查找前一个的max()或后续的min()。

答案 5 :(得分:0)

尝试类似:

SELECT * 
FROM your_table
WHERE (dt_time > argument_time and search_above = 'true')
   OR (dt_time < argument_time and search_above = 'false')
ORDER BY CASE WHEN search_above = 'true' 
              THEN dt_time - argument_time
              ELSE argument_time - dt_time
         END
LIMIT 1;