Snowflake 的时差替代 Postgres INTERVAL
Snowflake's time difference alternative to Postgres INTERVAL
我有以毫秒为单位的 UNIX 持续时间,需要将其转换为人类可读的格式。在 Postgres 中可以使用 INTERVAL 类型,但如何在 Snowflake 中完成?挑战在于其中一些值可能超过 24 小时。我已经在 Snowflake forum 上检查了类似问题的解决方案(对 ms 进行了调整)。但是不支持时间>24h
示例数据:
7200000 -- 2h
28800000 --8h
1800000 -- 30min
252000000 -- 70h
86400000 -- 24h
3593314 -- 59min 53sec
以便所需的输出看起来像:
02:00:00
08:00:00
00:30:00
70:00:00
24:00:00
00:59:53
可能是我搜索不好,但是至今没能找到解决这个问题的方法。
适用于 Postgres 的解决方案SELECT time_unix::bigint * INTERVAL '1 ms'
select *
,floor(ms/3600000) as hh
,floor((ms%3600000)/60000) as mm
,floor((ms%60000)/1000) as ss
,nullifzero(hh) as a1
,nullifzero(mm) as a2
,nullifzero(ss) as a3
,trim(nvl(a1||'h ','') || nvl(a2||'m ','') || nvl(a3||'s','')) as r
from values
(7200000, '2h'),
(28800000 , '8h'),
(1800000, '30min'),
(252000000, '70h'),
(86400000, '24h'),
(3593314, '59min 53sec')
t(ms, wanted)
给出:
MS
WANTED
HH
MM
SS
A1
A2
A3
R
7,200,000
2h
2
0
0
2
2h
28,800,000
8h
8
0
0
8
8h
1,800,000
30min
0
30
0
30
30m
252,000,000
70h
70
0
0
70
70h
86,400,000
24h
24
0
0
24
24h
3,593,314
59min 53sec
0
59
53
59
53
59m 53s
因此:
select *
,trim(nvl(nullifzero(floor(ms/3600000))||'h ','') || nvl(nullifzero(floor((ms%3600000)/60000))||'m ','') || nvl(nullifzero(floor((ms%60000)/1000))||'s','')) as r
from values
(7200000, '2h'),
(28800000 , '8h'),
(1800000, '30min'),
(252000000, '70h'),
(86400000, '24h'),
(3593314, '59min 53sec')
t(ms, wanted)
给出:
MS
WANTED
R
7,200,000
2h
2h
28,800,000
8h
8h
1,800,000
30min
30m
252,000,000
70h
70h
86,400,000
24h
24h
3,593,314
59min 53sec
59m 53s
或者我可以阅读:
select *
,trim(nvl(nullifzero(floor(ms/3600000))||'h ','') || nvl(nullifzero(floor((ms%3600000)/60000))||'m ','') || nvl(nullifzero(floor((ms%60000)/1000))||'s','')) as r
,lpad(floor(ms/3600000), 2, 0) || ':' || lpad(floor((ms%3600000)/60000), 2, 0) || ':' || lpad(floor((ms%60000)/1000), 2, 0) as r2
from values
(7200000, '2h'),
(28800000 , '8h'),
(1800000, '30min'),
(252000000, '70h'),
(86400000, '24h'),
(3593314, '59min 53sec')
t(ms, wanted)
MS
WANTED
R
R2
7,200,000
2h
2h
02:00:00
28,800,000
8h
8h
08:00:00
1,800,000
30min
30m
00:30:00
252,000,000
70h
70h
70:00:00
86,400,000
24h
24h
24:00:00
3,593,314
59min 53sec
59m 53s
00:59:53
想知道是否有人可以想出更糟糕的解决方案:)
create or replace function pginterval( TIME number )
returns varchar
language sql
as
$$
select LPAD( (extract( day from to_timestamp( TIME, 3 )) - 1 ) * 24 + extract( hour from to_timestamp( TIME, 3 )), 2, '0' )
|| ':' || right( to_timestamp( TIME, 3 )::time, 5 )
$$;
select pginterval( x )
from values
(7200000),
(28800000),
(1800000),
(252000000),
(86400000),
(3593314) tmp (x);
PGINTERVAL( X )
02:00:00
08:00:00
00:30:00
70:00:00
24:00:00
00:59:53
我有以毫秒为单位的 UNIX 持续时间,需要将其转换为人类可读的格式。在 Postgres 中可以使用 INTERVAL 类型,但如何在 Snowflake 中完成?挑战在于其中一些值可能超过 24 小时。我已经在 Snowflake forum 上检查了类似问题的解决方案(对 ms 进行了调整)。但是不支持时间>24h
示例数据:
7200000 -- 2h
28800000 --8h
1800000 -- 30min
252000000 -- 70h
86400000 -- 24h
3593314 -- 59min 53sec
以便所需的输出看起来像:
02:00:00
08:00:00
00:30:00
70:00:00
24:00:00
00:59:53
可能是我搜索不好,但是至今没能找到解决这个问题的方法。
适用于 Postgres 的解决方案SELECT time_unix::bigint * INTERVAL '1 ms'
select *
,floor(ms/3600000) as hh
,floor((ms%3600000)/60000) as mm
,floor((ms%60000)/1000) as ss
,nullifzero(hh) as a1
,nullifzero(mm) as a2
,nullifzero(ss) as a3
,trim(nvl(a1||'h ','') || nvl(a2||'m ','') || nvl(a3||'s','')) as r
from values
(7200000, '2h'),
(28800000 , '8h'),
(1800000, '30min'),
(252000000, '70h'),
(86400000, '24h'),
(3593314, '59min 53sec')
t(ms, wanted)
给出:
MS | WANTED | HH | MM | SS | A1 | A2 | A3 | R |
---|---|---|---|---|---|---|---|---|
7,200,000 | 2h | 2 | 0 | 0 | 2 | 2h | ||
28,800,000 | 8h | 8 | 0 | 0 | 8 | 8h | ||
1,800,000 | 30min | 0 | 30 | 0 | 30 | 30m | ||
252,000,000 | 70h | 70 | 0 | 0 | 70 | 70h | ||
86,400,000 | 24h | 24 | 0 | 0 | 24 | 24h | ||
3,593,314 | 59min 53sec | 0 | 59 | 53 | 59 | 53 | 59m 53s |
因此:
select *
,trim(nvl(nullifzero(floor(ms/3600000))||'h ','') || nvl(nullifzero(floor((ms%3600000)/60000))||'m ','') || nvl(nullifzero(floor((ms%60000)/1000))||'s','')) as r
from values
(7200000, '2h'),
(28800000 , '8h'),
(1800000, '30min'),
(252000000, '70h'),
(86400000, '24h'),
(3593314, '59min 53sec')
t(ms, wanted)
给出:
MS | WANTED | R |
---|---|---|
7,200,000 | 2h | 2h |
28,800,000 | 8h | 8h |
1,800,000 | 30min | 30m |
252,000,000 | 70h | 70h |
86,400,000 | 24h | 24h |
3,593,314 | 59min 53sec | 59m 53s |
或者我可以阅读:
select *
,trim(nvl(nullifzero(floor(ms/3600000))||'h ','') || nvl(nullifzero(floor((ms%3600000)/60000))||'m ','') || nvl(nullifzero(floor((ms%60000)/1000))||'s','')) as r
,lpad(floor(ms/3600000), 2, 0) || ':' || lpad(floor((ms%3600000)/60000), 2, 0) || ':' || lpad(floor((ms%60000)/1000), 2, 0) as r2
from values
(7200000, '2h'),
(28800000 , '8h'),
(1800000, '30min'),
(252000000, '70h'),
(86400000, '24h'),
(3593314, '59min 53sec')
t(ms, wanted)
MS | WANTED | R | R2 |
---|---|---|---|
7,200,000 | 2h | 2h | 02:00:00 |
28,800,000 | 8h | 8h | 08:00:00 |
1,800,000 | 30min | 30m | 00:30:00 |
252,000,000 | 70h | 70h | 70:00:00 |
86,400,000 | 24h | 24h | 24:00:00 |
3,593,314 | 59min 53sec | 59m 53s | 00:59:53 |
想知道是否有人可以想出更糟糕的解决方案:)
create or replace function pginterval( TIME number )
returns varchar
language sql
as
$$
select LPAD( (extract( day from to_timestamp( TIME, 3 )) - 1 ) * 24 + extract( hour from to_timestamp( TIME, 3 )), 2, '0' )
|| ':' || right( to_timestamp( TIME, 3 )::time, 5 )
$$;
select pginterval( x )
from values
(7200000),
(28800000),
(1800000),
(252000000),
(86400000),
(3593314) tmp (x);
PGINTERVAL( X ) |
---|
02:00:00 |
08:00:00 |
00:30:00 |
70:00:00 |
24:00:00 |
00:59:53 |