postgres sql window 函数 - 尝试根据日期合并 array_agg 和 employee_id
postgres sql window function - trying to consolidate array_agg based on date and employee_id
我目前正在使用 postgres,并且有一个 sql window 函数用于根据日期生成员工签入和签出时间。但它有缺陷。
CREATE OR REPLACE VIEW view_test
AS
SELECT row_number() OVER () AS id,
a.created_at::date AS created_at,
date_part('year'::text, a.created_at) AS year,
date_part('month'::text, a.created_at) AS month,
date_part('day'::text, a.created_at) AS day,
date_part('dow'::text, a.created_at) AS dow,
a.company_id,
a.employee_id,
e.employee_type,
array_agg(
CASE
WHEN a.activity_type = 1
THEN a.created_at::time(0)
ELSE NULL::time
END) AS time_in,
array_agg(
CASE
WHEN a.activity_type = 2
THEN a.created_at::time(0)
ELSE NULL::time
END) AS time_out
FROM attendance_table a
LEFT JOIN employee_table e ON e.id = a.employee_id
GROUP BY a.created_at, date_part('day'::text, a.created_at),
a.employee_id, a.company_id, e.employee_type
ORDER BY date_part('year'::text, a.created_at), date_part('month'::text, a.created_at),
date_part('day'::text, a.created_at), a.employee_id;
这会产生这个结果
我正在尝试以这种方式生成 time_in 和 time_out 是基于 created_at(日期)和 employee_id 合并的。这个想法是针对每个日期,我会知道员工的入住和退房时间。警告:如果数组中有记录,则不应出现 {NULL}。
我要操作的数据的视图和字段
https://docs.google.com/spreadsheets/d/1hn3w0mnezrV6_f-fPAKPZHuqdDjBBc_ArcgeBmgblq4/edit?usp=sharing
如何修改上面的 windows 函数 sql 视图,以便根据 created_at(日期)合并 time_in 和 time_out和 employee_id ? (最后一个屏幕截图是所需的输出)警告:如果数组中有记录,则不应出现 {NULL}。
更新(非常接近的答案但没有完全解决):
CREATE OR REPLACE VIEW view_group
as
SELECT
created_at,
year,
month,
day,
dow,
company_id,
employee_id,
array_agg(check_in) as time_in,
array_agg(check_out) as time_out
FROM
view_test, unnest(time_in) check_in, unnest(time_out) check_out
GROUP BY 1,2,3,4,5,6,7
它产生这个:
设法通过 unnest 连接数组。但请注意 NULL 仍然存在。如何删除 NULL(但如果什么都没有,NULL 应该在那里)?或有意义且可能的东西。
在不知道您的原始数据的情况下,我只能使用您当前的结果。
要将您的结果转换为预期结果,您可以简单地添加一个组步骤:
SELECT
created_at,
year,
month,
day,
dow,
company_id,
employee_id,
MAX(time_in) as time_in,
MAX(time_out) as time_out
FROM
-- <your query>
GROUP BY 1,2,3,4,5,6,7
编辑: 添加原始数据
您需要一个简单的枢轴步骤。这可以使用条件聚合(GROUP BY
和 FILTER
子句)实现:
SELECT
created_at::date,
company_id,
employee_id,
MAX(created_at::time) FILTER (WHERE activity_type = 1),
MAX(created_at::time) FILTER (WHERE activity_type = 2)
FROM
attendance
GROUP BY created_at::date, company_id, employee_id
我目前正在使用 postgres,并且有一个 sql window 函数用于根据日期生成员工签入和签出时间。但它有缺陷。
CREATE OR REPLACE VIEW view_test
AS
SELECT row_number() OVER () AS id,
a.created_at::date AS created_at,
date_part('year'::text, a.created_at) AS year,
date_part('month'::text, a.created_at) AS month,
date_part('day'::text, a.created_at) AS day,
date_part('dow'::text, a.created_at) AS dow,
a.company_id,
a.employee_id,
e.employee_type,
array_agg(
CASE
WHEN a.activity_type = 1
THEN a.created_at::time(0)
ELSE NULL::time
END) AS time_in,
array_agg(
CASE
WHEN a.activity_type = 2
THEN a.created_at::time(0)
ELSE NULL::time
END) AS time_out
FROM attendance_table a
LEFT JOIN employee_table e ON e.id = a.employee_id
GROUP BY a.created_at, date_part('day'::text, a.created_at),
a.employee_id, a.company_id, e.employee_type
ORDER BY date_part('year'::text, a.created_at), date_part('month'::text, a.created_at),
date_part('day'::text, a.created_at), a.employee_id;
这会产生这个结果
我正在尝试以这种方式生成 time_in 和 time_out 是基于 created_at(日期)和 employee_id 合并的。这个想法是针对每个日期,我会知道员工的入住和退房时间。警告:如果数组中有记录,则不应出现 {NULL}。
我要操作的数据的视图和字段
https://docs.google.com/spreadsheets/d/1hn3w0mnezrV6_f-fPAKPZHuqdDjBBc_ArcgeBmgblq4/edit?usp=sharing
如何修改上面的 windows 函数 sql 视图,以便根据 created_at(日期)合并 time_in 和 time_out和 employee_id ? (最后一个屏幕截图是所需的输出)警告:如果数组中有记录,则不应出现 {NULL}。
更新(非常接近的答案但没有完全解决):
CREATE OR REPLACE VIEW view_group
as
SELECT
created_at,
year,
month,
day,
dow,
company_id,
employee_id,
array_agg(check_in) as time_in,
array_agg(check_out) as time_out
FROM
view_test, unnest(time_in) check_in, unnest(time_out) check_out
GROUP BY 1,2,3,4,5,6,7
它产生这个:
设法通过 unnest 连接数组。但请注意 NULL 仍然存在。如何删除 NULL(但如果什么都没有,NULL 应该在那里)?或有意义且可能的东西。
在不知道您的原始数据的情况下,我只能使用您当前的结果。
要将您的结果转换为预期结果,您可以简单地添加一个组步骤:
SELECT
created_at,
year,
month,
day,
dow,
company_id,
employee_id,
MAX(time_in) as time_in,
MAX(time_out) as time_out
FROM
-- <your query>
GROUP BY 1,2,3,4,5,6,7
编辑: 添加原始数据
您需要一个简单的枢轴步骤。这可以使用条件聚合(GROUP BY
和 FILTER
子句)实现:
SELECT
created_at::date,
company_id,
employee_id,
MAX(created_at::time) FILTER (WHERE activity_type = 1),
MAX(created_at::time) FILTER (WHERE activity_type = 2)
FROM
attendance
GROUP BY created_at::date, company_id, employee_id