在 Snowflake 中创建数组
Create an array in Snowflake
我想创建一个由两个时间戳构成的数组。
之后以此为范围求出第一个元素和第二个元素的区别
目标是找到工作时间(早上 9 点到晚上 17 点)内时间戳之间的时差。
正确的方法应该是什么?我可以创建数组然后找到时差吗?
例如在第一条记录中,由于 started_at
是在 17pm 之后,因此数组的第一个元素必须是 "2021-05-19 09:00:00"
.
示例数据:
WITH t1 AS (
SELECT 'A' AS id, '2021-05-18 18:30:00'::timestamp AS started_at, '2021-05-19 09:30:00'::timestamp AS ended_at UNION ALL
SELECT 'B' AS id, '2021-05-19 15:30:00'::timestamp AS started_at, '2021-05-20 13:00:00'::timestamp AS ended_at
)
SELECT *
FROM t1
预期结果:
我们的想法是计算我们是否需要扩展范围,使用横向展平生成行并使用 case 语句计算时间戳。
演示:
WITH t1 AS (
SELECT 'A' AS id, '2021-05-18 18:30:00'::timestamp AS started_at, '2021-05-19 09:30:00'::timestamp AS ended_at UNION ALL
SELECT 'B' AS id, '2021-05-19 15:30:00'::timestamp AS started_at, '2021-05-20 13:00:00'::timestamp AS ended_at
)
select id, started_at, ended_at,
array_construct(
case when extend_before=1 and v.index=0 then started_at
when extend_before=1 then (dateadd(day,1,started_at::date)::string||' 09:00:00')::timestamp
when extend_before=0 and started_at > (started_at::date::string||' 17:00:00')::timestamp then (dateadd(day,1,started_at::date)::string||' 09:00:00')::timestamp
else started_at
end, --as calculated_started_at,
case when extend_before=1 and v.index=0 then (started_at::date::string||' 17:00:00')::timestamp
else ended_at
end --as calculated_ended_at
) as date_range,
datediff(minute,date_range[0],date_range[1]) minutes_diff
from
(
SELECT t1.*, case when started_at >= (started_at::date::string||' 17:00:00')::timestamp then 0 else 1 end as extend_before
FROM t1
) as s, lateral flatten(input=> split(space(s.extend_before),' '), outer => true) v
结果:
ID STARTED_AT ENDED_AT DATE_RANGE MINUTES_DIFF
A 2021-05-18 18:30:00.000 2021-05-19 09:30:00.000 ["2021-05-19 09:00:00.000", "2021-05-19 09:30:00.000"] 30
B 2021-05-19 15:30:00.000 2021-05-20 13:00:00.000 ["2021-05-19 15:30:00.000", "2021-05-19 17:00:00.000"] 90
B 2021-05-19 15:30:00.000 2021-05-20 13:00:00.000 ["2021-05-20 09:00:00.000", "2021-05-20 13:00:00.000"] 240
我想创建一个由两个时间戳构成的数组。 之后以此为范围求出第一个元素和第二个元素的区别
目标是找到工作时间(早上 9 点到晚上 17 点)内时间戳之间的时差。
正确的方法应该是什么?我可以创建数组然后找到时差吗?
例如在第一条记录中,由于 started_at
是在 17pm 之后,因此数组的第一个元素必须是 "2021-05-19 09:00:00"
.
示例数据:
WITH t1 AS (
SELECT 'A' AS id, '2021-05-18 18:30:00'::timestamp AS started_at, '2021-05-19 09:30:00'::timestamp AS ended_at UNION ALL
SELECT 'B' AS id, '2021-05-19 15:30:00'::timestamp AS started_at, '2021-05-20 13:00:00'::timestamp AS ended_at
)
SELECT *
FROM t1
预期结果:
我们的想法是计算我们是否需要扩展范围,使用横向展平生成行并使用 case 语句计算时间戳。
演示:
WITH t1 AS (
SELECT 'A' AS id, '2021-05-18 18:30:00'::timestamp AS started_at, '2021-05-19 09:30:00'::timestamp AS ended_at UNION ALL
SELECT 'B' AS id, '2021-05-19 15:30:00'::timestamp AS started_at, '2021-05-20 13:00:00'::timestamp AS ended_at
)
select id, started_at, ended_at,
array_construct(
case when extend_before=1 and v.index=0 then started_at
when extend_before=1 then (dateadd(day,1,started_at::date)::string||' 09:00:00')::timestamp
when extend_before=0 and started_at > (started_at::date::string||' 17:00:00')::timestamp then (dateadd(day,1,started_at::date)::string||' 09:00:00')::timestamp
else started_at
end, --as calculated_started_at,
case when extend_before=1 and v.index=0 then (started_at::date::string||' 17:00:00')::timestamp
else ended_at
end --as calculated_ended_at
) as date_range,
datediff(minute,date_range[0],date_range[1]) minutes_diff
from
(
SELECT t1.*, case when started_at >= (started_at::date::string||' 17:00:00')::timestamp then 0 else 1 end as extend_before
FROM t1
) as s, lateral flatten(input=> split(space(s.extend_before),' '), outer => true) v
结果:
ID STARTED_AT ENDED_AT DATE_RANGE MINUTES_DIFF
A 2021-05-18 18:30:00.000 2021-05-19 09:30:00.000 ["2021-05-19 09:00:00.000", "2021-05-19 09:30:00.000"] 30
B 2021-05-19 15:30:00.000 2021-05-20 13:00:00.000 ["2021-05-19 15:30:00.000", "2021-05-19 17:00:00.000"] 90
B 2021-05-19 15:30:00.000 2021-05-20 13:00:00.000 ["2021-05-20 09:00:00.000", "2021-05-20 13:00:00.000"] 240