动态(基于列)间隔


70

如何将动态(基于列)天数添加到NOW?

SELECT NOW() + INTERVAL a.number_of_days "DAYS" AS "The Future Date" 
FROM a;

a.number_of_days整数在哪里?

Answers:


182

我通常将数字乘以interval '1 day'或类似的数字,例如:

select now() + interval '1 day' * a.number_of_days from a;

6
7年后,这仍然是最好的解决方案。惊人。
greg_data

不错的技巧,但在我看来,更好的解决方案是使用CAST或:: interval将连接字段转换为间隔的解决方案。
DeniseMeander

Paul S有一个更灵活的解决方案。
乔纳森

28

我知道这已经是一岁了,但是如果您需要使用一列来指定实际间隔(例如,“天”,“月”),那么值得知道的是,您还可以将字符串CAST转换为间隔,给出:

SELECT now()+ CAST(the_duration||' '||the_interval AS Interval)

因此,原始问题将变为:

SELECT now() + CAST(a.number_of_days||" DAYS" AS Interval) as "The Future Date" FROM a;

1
如果要进一步控制“单位”列中的值,则可以自己对其进行解码:select *, num * case unit when 'W' then '1 week'::interval when 'D' then '1 day'::interval when 'H' then '1 hour'::interval end from (values(1,'W'),(2,'D'),(3,'H')) x(num, unit)
araqnid

谢谢,这对我很有帮助。但不要忘记更改postgres的引号:SELECT now() + CAST(a.number_of_days||' DAYS' AS Interval) as "The Future Date" FROM a;
leole

18

我更喜欢这种方式。我认为它非常简单和干净。在postgre中,您需要interval+operator与timestamp

select (3||' seconds')::interval;

select now()+ (10||' seconds')::interval,now();

您可以在其中使用秒,分钟...天,月...,也可以将数字替换为列。

select now()+ (column_name||' seconds')::interval,now()
from your_table;

3

要创建基于列值的间隔,建议在表中添加两列。例如,列“ period_value” :: INT4和列“ period_name” :: VARCHAR。列“ period_name”可以存储以下值:

  • 微秒
  • 毫秒
  • 第二
  • 分钟
  • 小时
  • 25美分硬币
  • 十年
  • 世纪
  • 千年
+ -------------- + ------------- +
| period_value | period_name |
+ -------------- + ------------- +
| 2 | 分钟|
+ -------------- + ------------- +

现在您可以编写:

SELECT NOW() - (period_value::TEXT || ' ' || period_name::TEXT)::INTERVAL FROM table;

本质上,您正在实现数据类型interval已经提供的功能。创建一个类型的单列interval将比此技巧更好。
a_horse_with_no_name

2

采用 make_interval()

SELECT NOW() + make_interval(days => a.number_of_days) AS "The Future Date" 
FROM a;

但总的来说,最好使用定义为的列interval,然后在其中存储值时可以使用任何所需的单位。


days => a.number_of_days似乎是Postgres的关键字语法以及make_interval仅具有用于参数yearsmonthsweeksdayshoursminssecs。这意味着它不适用于所有单位interval '1 millisecond' * msTime,但在大多数情况下仍是一个不错的选择。
VLRoyrenn

@VLRoyrenn:如果希望使用毫秒,则secs接受double valuesecs => 0.001
-a_horse_with_no_name

0

如果我们有带有间隔字符串值的字段,例如“ 41 years 11 mons 4 days”,并想将其转换为出生日期,请使用以下查询:

UPDATE "february14" set dob = date '2014/02/01'  - (patient_age::INTERVAL) 

dob是将'41 years 11 mons 4 days'转换 为 '1972/10/14'的日期字段,例如,
Patient_age是具有'41 years 11 mons 4 days'这样的字符串的varchar字段。

这是将年龄转换回出生日期的查询

SELECT now() - INTERVAL '41 years 10 mons 10 days';

0

基于列ID的更新是为我创建一些随机测试数据的有用方法。

update study_histories set last_seen_at = now() - interval '3 minutes' * id;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.