健身训练要一个半小时,上班一天8小时,休息20分钟,煮鸡蛋10分钟。这些都是时间区间的例子。
时间区间在实际开发里超有用,比如你要算任务截止时间、搞清楚两个日期差多少、或者加减点时间啥的。但在深入之前,先简单回顾下我们上节课讲到哪儿了。
在PostgreSQL里,INTERVAL是专门用来表示一段时间的数据类型。和其他时间类型不一样,它不存具体的日期或时间,而是描述一个区间,比如:"2天"、"3小时"、"5分钟"。
INTERVAL的语法
区间可以这样写:
INTERVAL '数字 时间单位'
举几个例子:
INTERVAL '2 days' -- 两天
INTERVAL '3 hours' -- 三小时
INTERVAL '15 minutes' -- 十五分钟
INTERVAL '1 day 2 hours' -- 一天两小时
PostgreSQL支持各种时间单位:year、month、day、hour、minute、second。你可以在一个表达式里随便组合。
在查询里用INTERVAL
INTERVAL数据类型和其他时间类型(DATE、TIMESTAMP)一起用的时候特别爽。下面是常见的操作。
给日期/时间加上区间
你可以把区间加到日期或时间上。比如:
SELECT CURRENT_DATE + INTERVAL '7 days' AS delivery_date;
-- 得到7天后的日期
结果:
| delivery_date |
|---|
| 2023-10-08 |
从日期/时间里减去区间
除了加,还能减:
SELECT NOW() - INTERVAL '2 hours' AS two_hours_ago;
-- 得到两小时前的时间
结果:
| two_hours_ago |
|---|
| 2023-10-01 10:00:00.000 |
计算两个日期的差值
INTERVAL很强大的一点就是能直接算两个日期的差:
SELECT '2023-10-15'::DATE - '2023-10-01'::DATE AS days_difference;
-- 两个日期之间差几天
结果:
| days_difference |
|---|
| 14 days |
注意,这里结果也是一个时间区间。
INTERVAL的实用例子
算送货日期。 假设有个网店,送货要3到7天。可以这样算可能的送货日期:
SELECT CURRENT_DATE + INTERVAL '3 days' AS earliest_delivery,
CURRENT_DATE + INTERVAL '7 days' AS latest_delivery;
结果:
| earliest_delivery | latest_delivery |
|---|---|
| 2023-10-04 | 2023-10-08 |
统计任务完成时间。 比如有个tasks表,每个任务有个开始时间。要算任务结束时间(按小时算):
CREATE TABLE tasks (
task_id SERIAL PRIMARY KEY,
task_name TEXT,
start_time TIMESTAMP,
duration INTERVAL
);
INSERT INTO tasks (task_name, start_time, duration)
VALUES
('准备报告', '2023-10-01 09:00:00', INTERVAL '4 hours'),
('测试应用', '2023-10-01 10:00:00', INTERVAL '2 hours 30 minutes');
SELECT task_name,
start_time,
start_time + duration AS end_time
FROM tasks;
结果:
| task_name | start_time | end_time |
|---|---|---|
| 准备报告 | 2023-10-01 09:00:00 | 2023-10-01 13:00:00 |
| 测试应用 | 2023-10-01 10:00:00 | 2023-10-01 12:30:00 |
比较任务耗时。 有时候我们想找出所有耗时少于3小时的任务:
SELECT task_name
FROM tasks
WHERE duration < INTERVAL '3 hours';
结果:
| task_name |
|---|
| 测试应用 |
INTERVAL的一些小技巧
动态计算区间。 可以把区间和别的操作结合起来。比如,把某个字段里的天数转成区间:
SELECT CURRENT_DATE + (order_days || ' days')::INTERVAL AS order_due_date
FROM orders;
把区间转成字符串。 有时候你想把区间转成字符串显示:
SELECT INTERVAL '2 days 3 hours'::TEXT AS interval_text;
结果:
| interval_text |
|---|
| 2 days 03:00:00 |
用INTERVAL常见的坑
虽然INTERVAL很强大,但用的时候也容易踩坑。最常见的就是格式写错。比如你写INTERVAL '2 hours and 30 minutes',PostgreSQL会报错,因为它不认识"and"。正确写法是:INTERVAL '2 hours 30 minutes'。
还有一种错法是忘了写时间单位,比如INTERVAL '2'。PostgreSQL不知道你这"2"是啥,所以一定要写清楚单位(2 days、2 hours)。
GO TO FULL VERSION