每月每一天的SQL Server 2008出勤报告

时间:2019-01-16 14:34:41

标签: sql sql-server report

我有两个表,一个叫ATTENDANCE,另一个叫DATES。

ATTENDANCE中,我有这样的行:

Name | when       | Entry | Exit 
-----+------------+-------+------
Bob  | 2019-01-02 | 08:00 | 16:00
Bob  | 2019-01-04 | 09:00 | 17:00
Bob  | 2019-01-05 | 07:00 | 13:00

并在DATES表中

DATE
----------
2019-01-01
2019-01-02
2019-01-03
...

我需要的是这样的报告,当为一月选择Bob时:

date       | entry | exit
-----------+-------+-----
2019-01-01 | null  | null
2019-01-02 | 08:00 | 16:00
2019-01-03 | null  | null
2019-01-04 | 09:00 | 17:00
2019-01-05 | null  | null
2019-01-06 | 07:00 | 13:00
2019-01-05 | null  | null
...

我尝试过这样的左联接:

select date, entry, exit 
from DATES
left join ATTENDANCE on date = when 
where name = 'Bob' 
  and month(date) = (select month('2019-01-01'))

但是我只能得到这个:

 2019-01-02 | 08:00 | 16:00
 2019-01-04 | 09:00 | 17:00
 2019-01-05 | 07:00 | 13:00

可以请人帮我吗?

谢谢 问候

2 个答案:

答案 0 :(得分:1)

您很近。您只需要将第二个表上的过滤移至on条件:

select d.date, a.entry, a.exit
from DATES d left join
     ATTENDANCE a
     on d.date = a.when and a.name = 'Bob' 
where MONTH(d.date) = MONTH('2019-01-01') and
      YEAR(d.date) = YEAR('2019-01-01')

注意:

  • 使用表别名。推荐的别名是表名的缩写。
  • 限定所有列名,以便知道它们来自哪个表。
  • 无需任何子查询即可从常量中提取月份。
  • 您应同时包括年份和月份。

写日期条件的更好方法是:

where d.date >= '2019-01-01' and
      d.date < '2019-01-01' + interval 1 month

这更好,因为优化器可以在date上使用索引(如果有)。

答案 1 :(得分:0)

您可以使用左联接并在ON子句中添加过滤条件

select d.date,a.entry,a.exit 
from DATES d 
left join ATTENDANCE a on a.date = d.date 
  and d.name = 'Bob' and MONTH (d.date) =  MONTH('2019-01-01')

然后将应用于与左联接表相关的列的条件用作内部联接..在这种情况下,将这些条件移至on子句