SQL“在时区”,查询范围宽,并带有“选择”所有列(tablename.*)表达式

SQL“在时区”,查询范围宽,并带有“选择”所有列(tablename.*)表达式,sql,postgresql,timezone,timestamp,Sql,Postgresql,Timezone,Timestamp,我在数据库中使用timestamp3和时区来表示表,如果需要,在我的情况下几乎都是这样 我需要选择表中的所有列,这可能是一个比下面更复杂的查询 我的问题是如何使用SQL at time zone为类似q.*的select表达式(其中一个是timestamp with time zone列)获取所需时区的timestamp with time zone。 我可能有同样情况的子查询。 对于查询范围,是否有一个表达式可以实现这一点 SELECT q.*, -- created_at times

我在数据库中使用timestamp3和时区来表示表,如果需要,在我的情况下几乎都是这样

我需要选择表中的所有列,这可能是一个比下面更复杂的查询

我的问题是如何使用SQL at time zone为类似q.*的select表达式(其中一个是timestamp with time zone列)获取所需时区的timestamp with time zone。 我可能有同样情况的子查询。 对于查询范围,是否有一个表达式可以实现这一点

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;

如果列的类型为timestamp,则使用AT TIME ZONE是将它们转换为特定时区的正确方法

但是,不要使用EET。使用特定的基于地点的时区,如欧洲/布加勒斯特-或任何适用于您的时区

或者,如果列的类型为timestamp with time zone,则可以设置会话的时区,postgres将为您进行转换:

SET TIME ZONE 'Europe/Bucharest'

您应该继续阅读以了解这两种时间戳类型的区别。

没有神奇的设置可以将数据类型timestamptz的所有列转换为timestamp。但您可以临时设置所需的目标时区,以调整timestamptz值的文本表示形式的显示:

这与应用AT时区构造不同,后者实际上将时间戳转换为时间戳,反之亦然。详情:

SET LOCAL的效果将持续到事务结束

就像一般情况一样,使用实际的时区名称比使用时区缩写要贵一些。时区名称考虑了DST和时区的其他特性:

SET LOCAL timezone = 'Europe/Istanbul';
演示
我现在有点糊涂了。在我的所有表格中,我都使用带时区的时间戳。我需要根据时区向不同的时区用户显示正确的时间表示。在编写时,我不做任何特殊的事情,只需插入或使用CREATE_时间戳。我的db可以位于不同于GMT的时区。但是,当我阅读时,我计划阅读at time zone子句,我将使用完整的时区名称,以便用户可以看到其时区中的时间。但我看到的唯一问题是at时区的语法,它不能应用于p.*中的一个字段。在阅读了提到的SO问题和其他一些问题之后,我得出了关于时间戳使用的结论和应用程序决定,非常感谢您@Erwin参与其中。我错过了什么吗?博士后怎么知道他们的时区?如果他们使用会话中设置的各自时区进行查询,则显示会自动调整。我将以某种方式从请求中获取他们的时区。我需要从用户那里获得正确查询Postgres的任何方法,无论是设置会话时区,还是使用at时区,我可能错误地认为使用第二个带有timestamp和timezone的SQL构造会得到一个丢弃5行的查询结果。查询已成功返回,20毫秒内没有结果。pgAdmin3 SQL编辑器中的消息。当我省略begin和commit时,它从表中给出了行,5行,也应用了上面设置的时区。原因是什么?通过“会话”,您是指当前事务还是查询,因为它也是隐式事务?请参阅。基本上,会话是默认的,其作用域为到db的整个连接。LOCAL用于当前事务。当前我在问题和类似问题中的查询中使用设置时区构造。但是,在设置的时区中不考虑post表内的时间戳,即连接中最左侧的第一个表。tags表中的那些是在指定的时间内由起始处的子句输出的。原因是什么?时间戳和时间戳是两种不同的类型。会话/本地时区设置仅影响timestamptz aka timestamp with time zone所有与时间和日期相关的字段均为my timestamp3,带有时区值,包括posts表和tags表中的时间戳。
SET LOCAL timezone = 'Europe/Istanbul';
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;