我选择从数据库时期的名单。 如果当前行是第一行则周期与日期开始,我能找到的间隔周期之间开始是这样的:
SELECT
...
CASE WHEN row_number() OVER(ORDER BY r.created_at ASC) = 1 THEN r.created_at - r.created_at::date ELSE NULL END AS period
...
FROM mytable r
我怎样才能做同样的最后一排? 为了找到最后一排和日期的午夜r.created_at之间的时间。
我所知道的first
和last
在PostgreSQL的(功能https://wiki.postgresql.org/wiki/First/last_(aggregate) ),但它们都是集合函数,在这种情况下,不要帮。
编辑:这个问题有2分伟大的答案。 在我的情况下,两个人都没有帮助,因为这一行我提出我的问题的一部分,是更大的查询的一部分,程序放在一起,并使用提供会逼我的解决方案,以改变的代码很多,对此我不愿意做的这点。 如果缩放问题命中 - 那么我肯定会重新考虑。
这可能是比窗函数更快:
with r as (
select
min(created_at) as min_created_at,
max(created_at) as max_created_at
from mytable
)
select
case when (select min_created_at from r) = created_at
then created_at - created_at::date else null
end as period_min,
case when (select max_created_at from r) = created_at
then created_at - created_at::date else null
end as period_max
from mytable
您可以使用窗口函数first_value()
和last_value()
在一个 CASE
语句:
SELECT *
, CASE WHEN ts IN ( first_value(created_at) OVER w
, last_value(created_at) OVER w)
THEN created_at::time::interval ELSE NULL END AS period
FROM tbl
WINDOW w AS (ORDER BY created_at rows BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING);
特殊要求在这里:你需要调整帧定义为last_value()
调用。 默认情况下,它是:
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
但是,你需要:
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
该first_value()
调用将使用默认框架的工作,但可以使用相同的为好。
我也得到了简化的计算period
。 您定义恰逢time
一的部分timestamp.
只投以time
为“截断”的日期部分: created_at::time
。
铸造于interval
后,这只是返回相同的数据类型为原始查询。
结果将被责令created_at
自动由于目前执行的窗口功能。 但不依赖于这一点。 如果你需要有序输出,加上明确的结尾:
ORDER BY created_at