我有以下架构,我稍微简化了一下:
CREATE TABLE [dbo].[Header] (
[HeaderId] [int] IDENTITY(1,1) NOT NULL,
[StaffId] [int] NOT NULL,
[WeekEnding] [smalldatetime] NOT NULL,
...
)
CREATE TABLE [dbo].[Staff] (
[StaffId] [int] NOT NULL,
[FirstWeekEnding] [smalldatetime] NULL,
...
)
Header表上的StaffId是外键。
Header表跟踪与员工相关的数据(在子表中未显示),如果子表中的数据存在,则对于给定的周,将有“周末”的条目。在这种情况下,“周末”始终是星期日。因此,样本数据可能如下所示:
HeaderId StaffId WeekEnding
---------------------------------
1 1 13/02/2011
2 1 20/02/2011
etc...
员工表上的“FirstWeekEnding”值是他们开始在Header表中跟踪信息的第一个日期。
我的问题
鉴于每个工作人员的第一周结束日期,如何构建一个查询,该查询将从Header表中提供截至当前日期的所有MISSING记录?
例如,给出以下数据:
StaffId FirstWeekEnding
---------------------------
1 02/01/2011
HeaderId StaffId WeekEnding
---------------------------------
1 1 02/01/2011
2 1 09/01/2011
3 1 16/01/2011
4 1 13/02/2011
5 1 20/02/2011
结果将是:
StaffId WeekEnding
---------------------
1 23/01/2011
1 30/01/2011
1 06/02/2011
理想情况下,查询应该处理多个工作人员,按其StaffId分组。
答案 0 :(得分:3)
您需要一种方法来生成日期系列。请参阅示例http://syntaxhelp.com/SQLServer/Recursive_CTE。然后搜索日期系列中没有匹配记录的条目。
DECLARE @startDate DATETIME, @endDate DATETIME
SELECT @startDate = '2011-01-02', @endDate = GETDATE()
;WITH DateSeries AS (
SELECT @startDate AS dt
UNION ALL
SELECT dt + 7 FROM DateSeries -- using 7 for weekly interval
WHERE dt + 7 <= @endDate
)
SELECT
*
FROM
DateSeries ds
LEFT JOIN
(your data here) t
ON
ds.dt = t.WeekEnding
WHERE
t.WeekEnding IS NULL
答案 1 :(得分:2)
假设您正在使用SQL 2005+,您可以为每个员工生成所有周,并尝试加入CTE中的Header表(类似,但可能不是这样):
;WITH cte AS
( SELECT StaffId, FirstWeekEnding AS WeekEnding
FROM STAFF
UNION ALL
SELECT StaffId, DATEADD(D, 7, WeekEnding) FROM cte
WHERE DATEADD(D, 7, WeekEnding) <= GETDATE()
)
SELECT StaffId, WeekEnding
FROM cte LEFT JOIN Header ON cte.StaffId = Header.StaffId AND cte.WeekEnding = Header.WeekEnding
WHERE Header.WeekEnding IS NULL
OPTION (MAXRECURSION 32767)
答案 2 :(得分:1)
好的,所以我建议创建一个Calendar表并加入。
这是最终查询:
select StaffID, BaseDate
From (
select
StaffID,
BaseDate,
(
Select count(*)
from Header h
where h.WeekEnding = c.BaseDate And h2.StaffID = h.StaffID
) as Count
From Header h, Calendar c ) as Subquery
Where Count = 0
日历:
create table Calendar (
BaseDate datetime primary key,
DayOfWeek varchar(10) not null,
WeekOfYear int not null,
MonthOfYear varchar(10) not null,
Quarter int not null
/* Add any other useful columns */
)
go
declare @d datetime
set @d = '20090101'
while @d < '20250101'
begin
insert into dbo.Calendar values (
@d,
datename(dw, @d),
datepart(ww, @d),
datename(mm, @d),
datepart(qq, @d))
set @d = dateadd(dd, 1, @d)
end
go
select *
from dbo.Calendar
where DayOfWeek = 'Sunday' and
BaseDate between '20090101' and '20250101'
go