0

我在 postgres 中有以下函数,它们只接受 timestampz 并将记录的年龄作为类似于 Reddit 的字符串返回:

CREATE OR REPLACE FUNCTION ageFromTimestamp (t timestamp WITH TIME ZONE) 
RETURNS text as $$
DECLARE interval text;
BEGIN
    case 
    when extract(years from age(now(), t)) > 0 then interval = extract(years from age(now(), t)) || 'y';
    when extract(months from age(now(), t)) > 0 then interval = extract(months from age(now(), t)) || 'mo';
    when extract(days from age(now(), t)) > 0 then interval = extract(days from age(now(), t)) || 'd';
    when extract(hours from age(now(), t)) > 0 then interval = extract(hours from age(now(), t)) || 'h';
    when extract(minutes from age(now(), t)) > 0 then interval = extract(minutes from age(now(), t)) || 'm';
    when extract(seconds from age(now(), t)) > 0 then interval = ceil(extract(seconds from age(now(), t))) || 's';
    else interval = 'now';
    end case;
    return interval;
END;
$$ language 'plpgsql';

这工作得很好。我只是好奇是否有更好的方法来防止计算extract(years from age(now(), t))两次?

我是 postgres 和 sql 的新手,所以学习新东西。

4

2 回答 2

0

CASE从技术上讲,如果您将您的更改为嵌套IF的并添加一个临时变量,则应该是可能的,例如:

CREATE OR REPLACE FUNCTION ageFromTimestamp (t timestamp WITH TIME ZONE) 
RETURNS text as $$
DECLARE 
    interval text;
    temp double precision;
BEGIN
    temp = extract(years from age(now(), t));
    IF temp > 0 THEN
        interval = extract(years from age(now(), t)) || 'y';
    ELSE
        temp = extract(months from age(now(), t));
        IF temp > 0 THEN
            interval = extract(months from age(now(), t)) || 'mo';
        ELSE
            ...
        END IF;
    END IF;
    return interval;
END;
$$ language 'plpgsql';

但是,这种方法有一个缺点:根据您的要求,它意味着 7 个嵌套IF的 's,这使得该函数很难阅读和维护。TBH,我会保持原样,除非您在使用它时遇到严重的性能滞后。

于 2019-09-08T17:38:41.540 回答
0

使用查询怎么样?

select (case when a.y > 0 then a.y || 'y'
             when a.m > 0 then a.m || 'mo'
             . . . 
        end)
from (values (age(now()) as v(a) cross apply
     (values ( extract(year from v.a),
               extract(month from v.a),
               . . .
             )
     ) a(y, mo, . . .)
于 2019-09-07T21:43:03.790 回答