如果发现当前行是从数据库中选择最后一排(Finding if current row is last

2019-10-19 16:09发布

我选择从数据库时期的名单。 如果当前行是第一行则周期与日期开始,我能找到的间隔周期之间开始是这样的:

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之间的时间。

我所知道的firstlast在PostgreSQL的(功能https://wiki.postgresql.org/wiki/First/last_(aggregate) ),但它们都是集合函数,在这种情况下,不要帮。

编辑:这个问题有2分伟大的答案。 在我的情况下,两个人都没有帮助,因为这一行我提出我的问题的一部分,是更大的查询的一部分,程序放在一起,并使用提供会逼我的解决方案,以改变的代码很多,对此我不愿意做的这点。 如果缩放问题命中 - 那么我肯定会重新考虑。

Answer 1:

这可能是比窗函数更快:

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


Answer 2:

您可以使用窗口函数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


文章来源: Finding if current row is last row to be selected from database