1

我目前正在使用 postgres,并且有这个 sql 窗口函数用于根据日期生成员工签入和签出时间。但它有缺陷。

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 (date) 和 employee_id 合并 time_in 和 time_out?(最后一个屏幕截图是所需的输出)警告:如果数组中有记录,则不应出现 {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 应该在那里)?或者一些有意义和可能的事情。

4

1 回答 1

1

在不知道您的原始数据的情况下,我只能使用您当前的结果。

要将您的结果转换为预期的结果,您可以简单地添加一个组步骤:

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 BYFILTER子句)来实现:

演示:db<>小提琴

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
于 2020-11-23T14:07:33.360 回答