I have a date column created_at
in a postgres table. I have a long running query that groups the data by week, so part of the query is
(SELECT TO_CHAR(score.created_at, 'IYYY-IW') AS week,
customer_id, AVG(score) AS avg_week_score FROM score
This is inefficient, and I would like to use the new generated column functionality in Postgres 12 to rather store a text version of each date as it is inserted.
I tried to run
alter table score add column gen_week text generated always as (TO_CHAR(created_at, 'IYYY-IW')) stored;
but got
ERROR: generation expression is not immutable
I guessed that this has to do with the fact that created_at is dependent on locale, and especially timezone, so I tried
alter table score add column week_gen text generated always as (TO_CHAR(created_at::timestamptz at time zone 'UTC', 'IYYY-IW')) stored;
to make the timezone explicit, but this produces the same error.
Is there a way to make to_char behave immutably with a date object, or do I have to define my own immutable function based on to_char?
The problem is that to_char()
could take modifies from the locale -- and functions either are or are not immutable.
You can do the same thing using extract()
:
alter table score add column gen_week text generated always as
((extract(isoyear from created_at) * 100 + extract(week from created_at))::text ) stored;
Actually, the above doesn't put the hyphen in, so:
alter table score add column gen_week text generated always as
(extract(isoyear from created_at)::text || '-' || lpad(extract(week from created_at)::text, 2, '0')) stored;
Here is a db<>fiddle.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.