SQL Server在结果集中选择缺少的日期

时间:2015-07-21 06:48:47

标签: sql sql-server sql-server-2008

我有一个包含空间分隔形式的员工每日出勤时间的表。

EmployeePunch

EmpID    EmpName    Date          Time

1        ABC        2014-12-01    10:00 18:00
1        ABC        2014-12-02    09:50 17:50
1        ABC        2014-12-04    09:30 17:30
1        ABC        2014-12-07    10:00 18:00
1        ABC        2014-12-08    09:50 17:50
1        ABC        2014-12-10    09:30 17:30

现在我想写一个关于以下输出的查询

EmpID    EmpName    Date          Time

1        ABC        2014-12-01    10:00 18:00
1        ABC        2014-12-02    09:50 17:50
1        ABC        2014-12-03    ABSENT
1        ABC        2014-12-04    09:30 17:30
1        ABC        2014-12-05    ABSENT
1        ABC        2014-12-06    ABSENT
1        ABC        2014-12-07    10:00 18:00
1        ABC        2014-12-08    09:50 17:50
1        ABC        2014-12-09    ABSENT
1        ABC        2014-12-10    09:30 17:30

2 个答案:

答案 0 :(得分:0)

首先定义CTE以生成缺失记录:

WITH dates AS (
SELECT DISTINCT EmpId, EmpName, '2014-12-01' AS Date, 'ABSENT' AS Time
FROM EmployeePunch
UNION
SELECT EmpId, EmpName, DATEADD(DAY, 1, Date), 'ABSENT'
FROM dates
WHERE Date < DATEADD(DAY, -1, DATEADD(MONTH, 1, '2014-12-01')))
SELECT * FROM dates

在下一步中,将最后一行替换为:

SELECT * FROM EmployeePunch
UNION ALL
SELECT d.* FROM dates d
LEFT JOIN EmployeePunch e
ON e.EmpId = d.EmpId AND e.Date = d.Date
WHERE e.Time IS NULL

缺少的行是外连接的行。

答案 1 :(得分:0)

没有CTE:

select ep1.EmpId, ep1.EmpName, a.Date, ISNULL(ep2.Time, 'ABSENT') as Time
from (
    select DATEADD(day, a.a + (10 * b.a) + (100 * c.a), CAST('2014-12-01' /*begin date*/ AS DATE)) as Date
    from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
) a cross apply (select distinct EmpId, EmpName from EmployeePunch) ep1 --on a.Date = f.Date
left join EmployeePunch ep2 on ep2.Date = a.Date and ep2.EmpId = ep1.EmpId
where a.Date <= '2014-12-10' and ep1.EmpId is not null

请注意最大允许范围 - 1000天,但必要时可以延长