簡體   English   中英

postgres sql GROUP BY DATE with LEFT JOIN 不列出右表中的所有記錄

[英]postgres sql GROUP BY DATE with LEFT JOIN does not list ALL records from the right table

我正在嘗試按出勤時間戳的日期分組,同時列出分組日期的所有員工。 而且無論是否有出勤記錄,我都想列出所有可用的員工。

這是我生成查詢的嘗試,但它沒有列出每個生成日期的所有員工。

請參考我嘗試的sql代碼: https://dbfiddle.uk/?rdbms=postgres_13&fiddle=a971a7ac01fb2f4bc7458983c40a24bf

SELECT 
    a.created_at::date as created_date,
    a.employee_id,
    e.name,
    e.division_id,
    MIN(a.created_at::time) FILTER (WHERE a.activity_type = 1) as min_time_in,
    MAX(a.created_at::time) FILTER (WHERE a.activity_type = 2) as max_time_out
FROM
   attendance a
LEFT JOIN employee e on e.id = a.employee_id   
GROUP BY created_date, a.employee_id, e.name, e.division_id
ORDER BY created_date, a.employee_id

結果顯示如下:

created_date    employee_id name    division_id min_time_in max_time_out
2020-11-18  1   John                    1       07:10:25    20:01:05
2020-11-18  2   Amber                   2       07:30:25    19:10:25
2020-11-18  3   Mike                    1       07:50:25    19:22:38
2020-11-19  1   John                    1       07:11:23    23:21:53

但是,我的目標是列出所有員工並按日期對 employee_id 記錄進行分組。 無論員工是否出勤,它都應該顯示一行日期。 如何生成如下所示的查詢:

created_date    employee_id name    division_id min_time_in max_time_out
2020-11-18  1   John                    1       07:10:25    20:01:05
2020-11-18  2   Amber                   2       07:30:25    19:10:25
2020-11-18  3   Mike                    1       07:50:25    19:22:38
2020-11-18  4   Jimmy                   1       null         null
2020-11-18  5   Kathy                   2       null         null
2020-11-19  1   John                    1       07:11:23    23:21:53
2020-11-19  2   Amber                   2       null         null
2020-11-19  3   Mike                    1       null         null
2020-11-19  4   Jimmy                   1       null         null
2020-11-19  5   Kathy                   2       null         null

這應該有效:

SELECT 
     d::date AS created_date
  ,  e.id
  ,  e.name
  ,  e.division_id
  ,  MIN(a.created_at::time) FILTER (WHERE a.activity_type = 1) as min_time_in
  ,  MAX(a.created_at::time) FILTER (WHERE a.activity_type = 2) as max_time_out
FROM    (SELECT MIN(created_at), MAX(created_at) FROM attendance) AS r(startdate,enddate)
  , generate_series(
        startdate::timestamp, 
        enddate::timestamp, 
        interval '1 day') g(d)
    CROSS JOIN  employee e
    LEFT JOIN   attendance a ON a.created_at::date = d::date AND e.id = a.employee_id
GROUP BY 
    created_date
  , e.id
  , e.name
  , e.division_id
ORDER BY 
    created_date
  , e.id;

編輯:所選員工的 id,而不是 employee_id

只需將出勤表中的不同日期與員工表交叉連接即可。 您可以嘗試如下:

select
a1. date,
e.id,
e.name,
e.division_id,
MIN(a.created_at::time) FILTER (WHERE a.activity_type = 1  ) as min_time_in,
MAX(a.created_at::time) FILTER (WHERE a.activity_type = 2) as max_time_out
from 
employee e left join (select distinct date(created_at) "date" from attendance ) a1 on true
left JOIN attendance a on e.id=a.employee_id and date(a.created_at)=a1.date
group by 1,2,3,4
order by 1,2

注意: left join on true相當於cross join

演示

更新:

如果您想要最小日期和最大日期之間的所有日期的 output。

with cte as (select min(created_at)::date "mindate", max(created_at)::date "maxdate" from attendance )

select
a1. date,
e.id,
e.name,
e.division_id,
MIN(a.created_at::time) FILTER (WHERE a.activity_type = 1  ) as min_time_in,
MAX(a.created_at::time) FILTER (WHERE a.activity_type = 2) as max_time_out
from 
employee e 
left join (select g.date from cte, generate_series(cte.mindate,cte.maxdate,interval '1 day') g(date) ) a1 on true
left JOIN attendance a on e.id=a.employee_id and date(a.created_at)=a1.date
group by 1,2,3,4
order by 1,2

演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM