我一直在尝试从时间戳字段中的第一个日期到最后一个日期生成一系列日期(YYYY-MM-DD HH)。我已经得到了我需要的generate_series()
,但是在尝试从表中获取开始和结束日期时遇到了问题。我有以下几点概括:
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
答案 0 :(得分:18)
你当然不需要CTE。这将比必要的更昂贵
并且您不需要转换为timestamp
,因为当您将timestamp
类型提供给generate_series()
时,结果已经 数据类型为date
。
在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);
可选择使用to_char()
以您提及的格式将结果作为文本获取
在早期(或任何)版本中:
SELECT generate_series(min(start_timestamp)
, max(start_timestamp)
, interval '1 hour') AS ts
FROM header_table;
但是在SELECT
列表中调用set-returns函数是一个非标准功能,并且有些人不赞成。如果可以,请使用第一个查询。
注意 NULL 处理的细微差别:
相当于
max(start_timestamp)
是通过
获得的ORDER BY start_timestamp DESC NULLS LAST
LIMIT 1
如果没有NULLS LAST
NULL值,则首先按降序排列(如果可以在start_timestamp
中为NULL值)。 <{1}}您将获得NULL,并且您的查询将显示为空。
详细说明:
答案 1 :(得分:4)
如何使用聚合函数呢?
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;
甚至:
select generate_series(min(start_timestamp),
max(start_timestamp),
'1 hour'::interval
)::timestamp as date_hour
from header_table;
答案 2 :(得分:2)
试试这个:
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:您希望 a 行中的2个日期,而不是单独的行。