SQL "AT TIME ZONE", широкий запрос и выражение "SELECT" всех столбцов (tablename. *)

Я использую timestamp(3) with time zone в своей базе данных для таблиц, когда это необходимо, это почти любой случай в моей ситуации.

Мне нужно выбрать все столбцы таблицы, возможно, в гораздо более сложном запросе, чем следующие.

Мой вопрос заключается в том, как получить временные метки (с часовым поясом) в нужном часовом поясе с помощью SQL at time zone '<TIMEZONE>' для выражения выбора типа q.*, одним из которых является столбец временной метки (с часовым поясом). У меня могут быть подзапросы с одинаковой ситуацией. Есть ли выражение для достижения этого для запроса?

SELECT
    q.*, -- created_at timestamp (with time zone) is already in here
    q.created_at AT TIME ZONE 'EET', --instead of this redundant column selection
    u.name AS author,
    u.reputation,
    CASE WHEN count(t.*)=0 THEN '[]' ELSE json_agg(t.*) END as tags
FROM posts q

-- authors
JOIN users u
ON q.author_id = u.id

-- tags
left join post_has_tag p_h_t
on q.id = p_h_t.post_id
left join tags t
on p_h_t.tag_id = t.id

WHERE q.post_type = 'question'
group by q.id, u.id;

Ответ 1

Если ваши столбцы имеют тип timestamp, то использование AT TIME ZONE - это правильный способ преобразования их в определенный часовой пояс.

Однако не используйте EET. Используйте этот часовой пояс из этого списка, например Europe/Bucharest - или все, что применимо для вас.

В качестве альтернативы, если ваши столбцы имеют тип timestamp with time zone, тогда вы можете установить часовой пояс сеанса, и postgres выполнит преобразование для вас:

SET TIME ZONE 'Europe/Bucharest'

Вы должны прочитать документы, чтобы понять разницу этих двух типов временных меток.

Ответ 2

Не существует волшебной установки для преобразования всех столбцов типа данных timestamptz в timestamp. Но вы можете установить желаемый целевой часовой пояс (временно), чтобы настроить дисплей (текстовое представление) значения timestamptz:

BEGIN;
SET LOCAL timezone = 'EET';
SELECT q.*, -- including created_at timestamp as original timestamptz type
     , u.name AS author,
     , ...

 -- do something with your data

COMMIT;  -- or ROLLBACK; doesn't matter for just SELECT

Это не то же самое, что использовать конструкцию AT TIME ZONE, которая фактически преобразует timestamp в timestamptz и наоборот. Подробности:

Эффекты SET LOCAL продолжаются до конца транзакции.

И (например, @Matt уже упоминал), он обычно (даже если немного дороже) предпочитает использовать фактические названия часовых поясов по аббревиатурам часового пояса. Названия часовых поясов учитывают DST и другие особенности часового пояса:

SET LOCAL timezone = 'Europe/Istanbul';

Demo

BEGIN;
SET timezone = 'Europe/Istanbul';
SELECT now();

now
-----------------------------
2016-08-29 22:39:09.275647+03

SET timezone = 'UTC';
SELECT now();

now
-----------------------------
2016-08-29 19:39:09.275647+00

COMMIT;