如何将来自不符合WHERE条件的联接表中的数据包含为空值(SQL)

时间:2019-04-05 02:38:36

标签: sql sql-server outer-join

我有2个表的雇员和病假,这两个雇员由Employee ID关联,基本上,病假表将具有一个请假的雇员的多个数据,我想按月份筛选数据病假,并将在过滤的月份内没有休病假的员工作为空值。

       EMPLOYEES                  MEDICAL
    |employee|ID|             |ID|DateOfLeave|
         A     1                1   2019/1/3
         B     2                1   2019/4/15
         C     3                2   2019/5/16
         D     4

我想出的sql语句过滤休假的特定月份,并计算他们在该月份休假的次数,例如一月,它还包括没有休假的员工为“ 0”的员工,但是拥有一月没有休假的员工根本没有出现在结果集中,我如何显示他们在一月份有0休假?

select employees.employee, employees.ID,
 count(medical.DateOfLeave) as NumberOfLeaves
from employees
left outer join medical on employees.ID = medical.ID
where (MONTH(DateOfLeave) = 1) or (medical.DateOfLeave is null)
group by employees.employee,employees.ID
           RESULT SET
    |Employee|ID|NumberOfLeaves|
        A      1      1
        C      3      0   
        D      4      0

您可以看到B消失了,但是我希望它像雇员C和D一样在结果集中显示为“ 0”

我知道这是因为员工B的医疗数据不满足where子句的条件,但是我该如何写一个语句,其中包含在1月的结果集中为0的没有医疗假的员工? >

2 个答案:

答案 0 :(得分:0)

您的查询仅显示一月份休假或根本没有休假的员工的结果。

相反,如果只存在指定月份的记录,则只希望加入医疗表中的记录,然后将结果分组并从那里获取计数。

为此,您需要更改加入条件以包括“月份”过滤器。

这是一个使用表变量的工作示例

DECLARE @Employees TABLE (ID INT, Employee CHAR(1))
DECLARE @Medical TABLE (ID INT, DateOfLeave DATE)

INSERT INTO @Employees
VALUES (1, 'A'), (2,'B'), (3,'C'), (4, 'D')

INSERT INTO @Medical 
VALUES (1, '2019-01-03'), (1, '2019-04-15'), (2, '2019-05-16')

SELECT          e.employee, 
                e.ID,
                count(m.DateOfLeave) AS NumberOfLeaves
FROM            @Employees e
LEFT OUTER JOIN @Medical m ON   e.ID = m.ID AND MONTH(DateOfLeave) = 1
GROUP BY        e.employee,e.ID

答案 1 :(得分:0)

左外部联接将首先联接表,然后进行过滤。在您的情况下,B留在联接本身中,这就是为什么过滤器不起作用的原因。你可以试试这个

select employees.employee, employees.ID,
 nvl(count(medical.DateOfLeave),0) as NumberOfLeaves
from employees
left outer join (select * from medical 
where (MONTH(DateOfLeave) = 1)) 
on employees.ID = medical.ID
group by employees.employee,employees.ID

或者您也可以尝试

   select e.id, employee, count(dateofleave)
from employee e, medical m
where e.id = m.id
and month(m.DateOfLeave) = 1
group by e.id, employee
UNION ALL
select id, employee, 0
from employee e
where not exists(select 1 from medical m
where e.id = m.id
and month(m.DateOfLeave) = 1