将字符串时间戳转换为 Oracle 中的本地时区
Converting string timestamp to local-time zone in Oracle
我正在尝试使用 oracle 数据库汇总全球多个移动电话号码的数据使用量,为了获得准确的结果,我的 SQL 查询需要将此字符串时间戳转换为我的本地时区 +03 ,例如转换为 +03 时区后第一个数字 7803128475
的预期时间应该是
20190606085959
我当前的查询不准确
select sum(data_usage) where timestamp between '20190601000000' and '20190630235959';
`+-------------+------------+----------------+----------+
| MSISDN | DATA_USAGE | TIMESTAMP | TIMEZONE |
+-------------+------------+----------------+----------+
| 7803128475 | 1223.323 | 20190606135959 | +08:00 |
| 78093678473 | 1323.323 | 20190607071259 | +05:00 |
| 79093648472 | 1423.323 | 20190609090659 | -06:00 |
+-------------+------------+----------------+----------+`
您可以将字符串转换为实时时间戳:
to_timestamp(TIMESTAMP, 'YYYYMMDDHH24MISS')
然后您可以说明所在的时区:
from_tz(to_timestamp(TIMESTAMP, 'YYYYMMDDHH24MISS'), TIMEZONE)
或者您可以组合两个字符串列并将两者一起转换:
to_timestamp_tz(TIMESTAMP || TIMEZONE, 'YYYYMMDDHH24MISSTZH:TZM')
(你的列名很混乱,所以我把它们都写成大写的,以便更清楚地区分它们...)
无论哪种方式,您都可以通过以下方式将其转换为您当地的时区:
from_tz(to_timestamp(TIMESTAMP, 'YYYYMMDDHH24MISS'), TIMEZONE) at local
或者更清楚地表明它正在使用会话时区:
from_tz(to_timestamp(TIMESTAMP, 'YYYYMMDDHH24MISS'), TIMEZONE) at time zone sessiontimezone
或者如果您真的想要数据库时区:
from_tz(to_timestamp(TIMESTAMP, 'YYYYMMDDHH24MISS'), TIMEZONE) at time zone dbtimezone
将您的示例数据作为 CTE 可以为您提供:
alter session set time_zone = 'Asia/Baghdad';
-- CTE for sample data
with your_table (MSISDN, DATA_USAGE, TIMESTAMP, TIMEZONE) as (
select '7803128475', 1223.323, '20190606135959', '+08:00' from dual
union all
select '78093678473', 1323.323, '20190607071259', '+05:00' from dual
union all
select '79093648472', 1423.323, '20190609090659', '-06:00' from dual
)
-- example query
select MSISDN, DATA_USAGE, TIMESTAMP, TIMEZONE,
to_timestamp(TIMESTAMP, 'YYYYMMDDHH24MISS') as ts,
from_tz(to_timestamp(TIMESTAMP, 'YYYYMMDDHH24MISS'), TIMEZONE) as tstz,
from_tz(to_timestamp(TIMESTAMP, 'YYYYMMDDHH24MISS'), TIMEZONE) at local as local_tstz
from your_table;
MSISDN DATA_USAGE TIMESTAMP TIMEZO TS TSTZ LOCAL_TSTZ
----------- ---------- -------------- ------ --------------------- ---------------------------- ----------------------------------
7803128475 1223.323 20190606135959 +08:00 2019-06-06 13:59:59.0 2019-06-06 13:59:59.0 +08:00 2019-06-06 08:59:59.0 ASIA/BAGHDAD
78093678473 1323.323 20190607071259 +05:00 2019-06-07 07:12:59.0 2019-06-07 07:12:59.0 +05:00 2019-06-07 05:12:59.0 ASIA/BAGHDAD
79093648472 1423.323 20190609090659 -06:00 2019-06-09 09:06:59.0 2019-06-09 09:06:59.0 -06:00 2019-06-09 18:06:59.0 ASIA/BAGHDAD
如果您只打算在 where 子句过滤器中使用转换后的时间,那么您根本不需要将其转换为本地时区,只要您说出您要比较的时区即可它与;我会使用 >=
和 <
而不是 between
:
select sum(DATA_USAGE)
from your_table
where from_tz(to_timestamp(TIMESTAMP, 'YYYYMMDDHH24MISS'), TIMEZONE)
>= timestamp '2019-06-01 00:00:00 Asia/Baghdad'
and from_tz(to_timestamp(Timestamp, 'YYYYMMDDHH24MISS'), TIMEZONE)
< timestamp '2019-07-01 00:00:00 Asia/Baghdad'
SUM(DATA_USAGE)
---------------
3969.969
警告 该解决方案仅适用于几个 Oracle 11g 版本,请参阅评论。仅供参考。
多一个选项(TO_TIMESTAMP(TIMESTAMP, 'YYYYMMDDHH24MISS') AT TIME ZONE TIMEZONE) AT TIME ZONE sessiontimezone
演示
with yourTable (MSISDN, DATA_USAGE, TIMESTAMP, TIMEZONE) as (
select '7803128475', 1223.323, '20190606135959', '+08:00' from dual
union all
select '78093678473', 1323.323, '20190607071259', '+05:00' from dual
union all
select '79093648472', 1423.323, '20190609090659', '-06:00' from dual
)
select (TO_TIMESTAMP(TIMESTAMP, 'YYYYMMDDHH24MISS') AT TIME ZONE TIMEZONE) AT TIME ZONE '+05:00' t2
from yourTable;
T2
06-JUN-19 10.59.59.000000000 AM +05:00
07-JUN-19 07.12.59.000000000 AM +05:00
09-JUN-19 08.06.59.000000000 PM +05:00
我正在尝试使用 oracle 数据库汇总全球多个移动电话号码的数据使用量,为了获得准确的结果,我的 SQL 查询需要将此字符串时间戳转换为我的本地时区 +03 ,例如转换为 +03 时区后第一个数字 7803128475
的预期时间应该是
20190606085959
我当前的查询不准确
select sum(data_usage) where timestamp between '20190601000000' and '20190630235959';
`+-------------+------------+----------------+----------+
| MSISDN | DATA_USAGE | TIMESTAMP | TIMEZONE |
+-------------+------------+----------------+----------+
| 7803128475 | 1223.323 | 20190606135959 | +08:00 |
| 78093678473 | 1323.323 | 20190607071259 | +05:00 |
| 79093648472 | 1423.323 | 20190609090659 | -06:00 |
+-------------+------------+----------------+----------+`
您可以将字符串转换为实时时间戳:
to_timestamp(TIMESTAMP, 'YYYYMMDDHH24MISS')
然后您可以说明所在的时区:
from_tz(to_timestamp(TIMESTAMP, 'YYYYMMDDHH24MISS'), TIMEZONE)
或者您可以组合两个字符串列并将两者一起转换:
to_timestamp_tz(TIMESTAMP || TIMEZONE, 'YYYYMMDDHH24MISSTZH:TZM')
(你的列名很混乱,所以我把它们都写成大写的,以便更清楚地区分它们...)
无论哪种方式,您都可以通过以下方式将其转换为您当地的时区:
from_tz(to_timestamp(TIMESTAMP, 'YYYYMMDDHH24MISS'), TIMEZONE) at local
或者更清楚地表明它正在使用会话时区:
from_tz(to_timestamp(TIMESTAMP, 'YYYYMMDDHH24MISS'), TIMEZONE) at time zone sessiontimezone
或者如果您真的想要数据库时区:
from_tz(to_timestamp(TIMESTAMP, 'YYYYMMDDHH24MISS'), TIMEZONE) at time zone dbtimezone
将您的示例数据作为 CTE 可以为您提供:
alter session set time_zone = 'Asia/Baghdad';
-- CTE for sample data
with your_table (MSISDN, DATA_USAGE, TIMESTAMP, TIMEZONE) as (
select '7803128475', 1223.323, '20190606135959', '+08:00' from dual
union all
select '78093678473', 1323.323, '20190607071259', '+05:00' from dual
union all
select '79093648472', 1423.323, '20190609090659', '-06:00' from dual
)
-- example query
select MSISDN, DATA_USAGE, TIMESTAMP, TIMEZONE,
to_timestamp(TIMESTAMP, 'YYYYMMDDHH24MISS') as ts,
from_tz(to_timestamp(TIMESTAMP, 'YYYYMMDDHH24MISS'), TIMEZONE) as tstz,
from_tz(to_timestamp(TIMESTAMP, 'YYYYMMDDHH24MISS'), TIMEZONE) at local as local_tstz
from your_table;
MSISDN DATA_USAGE TIMESTAMP TIMEZO TS TSTZ LOCAL_TSTZ
----------- ---------- -------------- ------ --------------------- ---------------------------- ----------------------------------
7803128475 1223.323 20190606135959 +08:00 2019-06-06 13:59:59.0 2019-06-06 13:59:59.0 +08:00 2019-06-06 08:59:59.0 ASIA/BAGHDAD
78093678473 1323.323 20190607071259 +05:00 2019-06-07 07:12:59.0 2019-06-07 07:12:59.0 +05:00 2019-06-07 05:12:59.0 ASIA/BAGHDAD
79093648472 1423.323 20190609090659 -06:00 2019-06-09 09:06:59.0 2019-06-09 09:06:59.0 -06:00 2019-06-09 18:06:59.0 ASIA/BAGHDAD
如果您只打算在 where 子句过滤器中使用转换后的时间,那么您根本不需要将其转换为本地时区,只要您说出您要比较的时区即可它与;我会使用 >=
和 <
而不是 between
:
select sum(DATA_USAGE)
from your_table
where from_tz(to_timestamp(TIMESTAMP, 'YYYYMMDDHH24MISS'), TIMEZONE)
>= timestamp '2019-06-01 00:00:00 Asia/Baghdad'
and from_tz(to_timestamp(Timestamp, 'YYYYMMDDHH24MISS'), TIMEZONE)
< timestamp '2019-07-01 00:00:00 Asia/Baghdad'
SUM(DATA_USAGE)
---------------
3969.969
警告 该解决方案仅适用于几个 Oracle 11g 版本,请参阅评论。仅供参考。
多一个选项(TO_TIMESTAMP(TIMESTAMP, 'YYYYMMDDHH24MISS') AT TIME ZONE TIMEZONE) AT TIME ZONE sessiontimezone
演示
with yourTable (MSISDN, DATA_USAGE, TIMESTAMP, TIMEZONE) as (
select '7803128475', 1223.323, '20190606135959', '+08:00' from dual
union all
select '78093678473', 1323.323, '20190607071259', '+05:00' from dual
union all
select '79093648472', 1423.323, '20190609090659', '-06:00' from dual
)
select (TO_TIMESTAMP(TIMESTAMP, 'YYYYMMDDHH24MISS') AT TIME ZONE TIMEZONE) AT TIME ZONE '+05:00' t2
from yourTable;
T2
06-JUN-19 10.59.59.000000000 AM +05:00
07-JUN-19 07.12.59.000000000 AM +05:00
09-JUN-19 08.06.59.000000000 PM +05:00