时区日期相关语法和语义差异
date at time zone related syntax and semantic differences
问题:查询 1 "semantically" 与查询 2 有何不同?
背景:
- 从位于我本地时区(AT TIME ZONE 'America/New_York')的数据库中的 table 中提取数据。
- table有'America/Los_Angeles'、America/North_Dakota/New_Salem等各个时区的数据。
(Postgres 将 table 数据存储在我本地时区的各个时区)
- 因此,每次我检索本地时间以外的其他位置的数据时,我都会将其转换为相关时区以进行评估。
查询 1:
test_db=# select count(id) from click_tb where date::date AT TIME ZONE 'America/Los_Angeles' = '2017-05-22'::date AT TIME ZONE 'America/Los_Angeles';
count
-------
1001
(1 row)
查询 2:
test_db=# select count(id) from click_tb where (date AT TIME ZONE 'America/Los_Angeles')::date = '2017-05-22'::date;
count
-------
5
(1 row)
Table结构:
test_db=# /d+ click_tb
Table "public.click_tb"
Column | Type | Modifiers | Storage | Stats target | Description
-----------------------------------+--------------------------+-------------------------------------------------------------+----------+--------------+-------------
id | integer | not null default nextval('click_tb_id_seq'::regclass) | plain | |
date | timestamp with time zone | | plain | |
Indexes:
"click_tb_id" UNIQUE CONSTRAINT, btree (id)
"click_tb_date_index" btree (date)
The query 1 and query 2 do not produce consistent results.
As per my tests, the below query 3, semantically addresses my requirement.
Your critical feedback is welcome.
Query 3:
test_db=# select count(id) from click_tb where ((date AT TIME ZONE 'America/Los_Angeles')::timestamp with time zone)::date = '2017-05-22'::date;
不转换时间戳字段。相反,进行范围查询。由于您的数据已经在使用 timestamp with time zone
类型,因此只需相应地设置查询的时区。
set TimeZone = 'America/Los_Angeles';
select count(id) from click_tb
where date >= '2017-01-02'
and date < '2017-01-03';
请注意这是如何使用日期的半开间隔(在设置时区的一天开始时)。如果你想从你的第一个日期计算第二个日期,那么:
set TimeZone = 'America/Los_Angeles';
select count(id) from click_tb
where date >= '2017-01-02'
and date < (timestamp with time zone '2017-01-02' + interval '1 day');
这可以正确处理夏令时和可商价性。
问题:查询 1 "semantically" 与查询 2 有何不同?
背景:
- 从位于我本地时区(AT TIME ZONE 'America/New_York')的数据库中的 table 中提取数据。
- table有'America/Los_Angeles'、America/North_Dakota/New_Salem等各个时区的数据。 (Postgres 将 table 数据存储在我本地时区的各个时区)
- 因此,每次我检索本地时间以外的其他位置的数据时,我都会将其转换为相关时区以进行评估。
查询 1:
test_db=# select count(id) from click_tb where date::date AT TIME ZONE 'America/Los_Angeles' = '2017-05-22'::date AT TIME ZONE 'America/Los_Angeles';
count
-------
1001
(1 row)
查询 2:
test_db=# select count(id) from click_tb where (date AT TIME ZONE 'America/Los_Angeles')::date = '2017-05-22'::date;
count
-------
5
(1 row)
Table结构:
test_db=# /d+ click_tb
Table "public.click_tb"
Column | Type | Modifiers | Storage | Stats target | Description
-----------------------------------+--------------------------+-------------------------------------------------------------+----------+--------------+-------------
id | integer | not null default nextval('click_tb_id_seq'::regclass) | plain | |
date | timestamp with time zone | | plain | |
Indexes:
"click_tb_id" UNIQUE CONSTRAINT, btree (id)
"click_tb_date_index" btree (date)
The query 1 and query 2 do not produce consistent results. As per my tests, the below query 3, semantically addresses my requirement. Your critical feedback is welcome.
Query 3:
test_db=# select count(id) from click_tb where ((date AT TIME ZONE 'America/Los_Angeles')::timestamp with time zone)::date = '2017-05-22'::date;
不转换时间戳字段。相反,进行范围查询。由于您的数据已经在使用 timestamp with time zone
类型,因此只需相应地设置查询的时区。
set TimeZone = 'America/Los_Angeles';
select count(id) from click_tb
where date >= '2017-01-02'
and date < '2017-01-03';
请注意这是如何使用日期的半开间隔(在设置时区的一天开始时)。如果你想从你的第一个日期计算第二个日期,那么:
set TimeZone = 'America/Los_Angeles';
select count(id) from click_tb
where date >= '2017-01-02'
and date < (timestamp with time zone '2017-01-02' + interval '1 day');
这可以正确处理夏令时和可商价性。