[英]Generate_series in Postgres from start and end date in a table
I have been trying to generate a series of dates (YYYY-MM-DD HH) from the first until the last date in a timestamp field.我一直在尝试在时间戳字段中从第一个日期到最后一个日期生成一系列日期 (YYYY-MM-DD HH)。 I've got the generate_series()
I need, however running into an issue when trying to grab the start and end dates from a table.我有我需要的generate_series()
,但是在尝试从表中获取开始和结束日期时遇到问题。 I have the following to give a rough idea:我有以下几点可以给出一个粗略的想法:
with date1 as
(
SELECT start_timestamp as first_date
FROM header_table
ORDER BY start_timestamp DESC
LIMIT 1
),
date2 as
(
SELECT start_timestamp as first_date
FROM header_table
ORDER BY start_timestamp ASC
LIMIT 1
)
select generate_series(date1.first_date, date2.first_date
, '1 hour'::interval)::timestamp as date_hour
from
( select * from date1
union
select * from date2) as foo
Postgres 9.3 Postgres 9.3
You don't need a CTE for this, that would be more expensive than necessary.为此您不需要 CTE,那会比必要的贵。
And you don't need to cast to timestamp
, the result already is of data type timestamp
when you feed timestamp
types to generate_series()
.并且您不需要强制转换为timestamp
,当您将timestamp
类型提供给generate_series()
timestamp
,结果已经是数据类型timestamp
。 Details here:详情在这里:
In Postgres 9.3 or later you can use a LATERAL
join:在 Postgres 9.3或更高版本中,您可以使用LATERAL
连接:
SELECT to_char(ts, 'YYYY-MM-DD HH24') AS formatted_ts
FROM (
SELECT min(start_timestamp) as first_date
, max(start_timestamp) as last_date
FROM header_table
) h
, generate_series(h.first_date, h.last_date, interval '1 hour') g(ts);
Optionally with to_char()
to get the result as text in the format you mentioned.可选择使用to_char()
以您提到的格式将结果作为文本获取。
This works in any Postgres version:这适用于任何Postgres 版本:
SELECT generate_series(min(start_timestamp)
, max(start_timestamp)
, interval '1 hour') AS ts
FROM header_table;
Typically a bit faster.通常会快一点。
Calling set-returning functions in the SELECT
list is a non-standard-SQL feature and frowned upon by some.在SELECT
列表中调用 set-returning 函数是一个非标准的 SQL 功能,有些人不赞成。 Also, there were behavioral oddities (though not for this simple case) that were eventually fixed in Postgres 10. See:此外,在 Postgres 10 中最终修复了一些行为古怪(虽然不是这个简单的案例)。请参阅:
Note a subtle difference in NULL handling:请注意NULL处理的细微差别:
The equivalent of相当于
max(start_timestamp)
is obtained with是用
ORDER BY start_timestamp DESC NULLS LAST
LIMIT 1
Without NULLS LAST
NULL values come first in descending order (if there can be NULL values in start_timestamp
).没有NULLS LAST
NULL 值按降序排在第一位(如果start_timestamp
可以有 NULL 值)。 You would get NULL for last_date
and your query would come up empty.你会得到 NULL 的last_date
并且你的查询会last_date
空的。
Details:细节:
How about using aggregation functions instead?改用聚合函数怎么样?
with dates as (
SELECT min(start_timestamp) as first_date, max(start_timestamp) as last_date
FROM header_table
)
select generate_series(first_date, last_date, '1 hour'::interval)::timestamp as date_hour
from dates;
Or even:甚至:
select generate_series(min(start_timestamp),
max(start_timestamp),
'1 hour'::interval
)::timestamp as date_hour
from header_table;
try this:尝试这个:
with dateRange as
(
SELECT min(start_timestamp) as first_date, max(start_timestamp) as last_date
FROM header_table
)
select
generate_series(first_date, last_date, '1 hour'::interval)::timestamp as date_hour
from dateRange
NB: You want the 2 dates in a row, not on separate rows.注意:您要在连续2日,而不是单独的行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.