我有一个Postgres表,它将创建的时间戳记存储在created_date DATE
列中,并在created_time INT
列中存储自午夜以来的秒数。
我想根据创建的时间戳进行选择。
在MySQL中,我会写:
SELECT * FROM MyCustomers
WHERE ADDTIME(created_date,SEC_TO_TIME(created_time)) > 'somedateliteral'
在PostgreSQL中看起来如何?
我可以在手册中看到示例,但是它们都使用文字值,而不是表列中的值。
只需将两者加在一起:
created_date + created_time * interval '1 second' > ?
您可以使用make_interval()
将分钟变成一个间隔,然后可以将其添加到date
列中以构造适当的timestamp
:
created_date + make_interval(secs => created_time)
假设ISO format等于'somedateliteral'
。由于它应该是时间戳文字,因此我将其命名为'timestamp_literal'
。
SELECT *, created_date + make_interval(secs => created_time) AS created_at
FROM mycustomers
WHERE (created_date, created_time)
> (date 'timestamp_literal', EXTRACT(epoch FROM time 'timestamp_literal')::int);
date 'timestamp_literal'
和time 'timestamp_literal'
从文字中获取相应的日期/时间部分。 (如果没有时间部分,后者会中断,而显然前者也可以使用日期文字)。
使其“可精炼”。参见:
与动态计算时间戳的解决方案相反,该查询可以使用基本的multicolumn index:
CREATE INDEX multicolumn_created ON mycustomers (created_date, created_time);
(¹您可以创建一个匹配的表达式索引以使其起作用...)
Postgres可以通过ROW值比较完美地使用此索引。 (我上次看,MySQL无法做到这一点。)请参阅:
将时间戳存储为date
+ integer
通常是没有益处的设计错误。请改用timestamp
。您可能需要切换到通常首选的timestamptz
。参见:
[其他答案已经提供了将(date, integer)
转换为timestamp
的表达式-您可以使用它来修复表格:
BEGIN;
-- drop all depending objects: indexes, views, ...
ALTER TABLE mycustomers
ALTER created_date TYPE timestamp
USING (created_date + make_interval(secs => created_time))
, DROP COLUMN created_time;
ALTER TABLE mycustomers RENAME created_date TO created_at; -- or whatever
-- recreate all depending objects: indexes, views, ...
COMMIT;
很明显,使用这些列采用所有查询。眼前的查询变成:
SELECT * FROM mycustomers WHERE created_at > 'somedateliteral';
db <>小提琴here