我有一个带有唯一日期时间字段的postgres表。 我想使用/创建一个函数,该函数将日期时间值作为参数,并返回与传递的日期时间值相关(但不相等)的最近日期时间的行ID。第二个参数可以在之前指定,在之后指定传递的值。
理想情况下,本机datetime functions的某些组合可以处理此要求。否则它必须是自定义功能。
问题:在一组行上查询相对日期时间的方法是什么?
答案 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;