Sql server 从SQL Server 2012中的列表返回缺少的日期
考虑到过滤器: 开始日期:2015年9月14日星期一 完:2015年9月20日星期日 我从2009年14月至2009年20月的查询中得到了以下结果:Sql server 从SQL Server 2012中的列表返回缺少的日期,sql-server,tsql,sql-server-2012,Sql Server,Tsql,Sql Server 2012,考虑到过滤器: 开始日期:2015年9月14日星期一 完:2015年9月20日星期日 我从2009年14月至2009年20月的查询中得到了以下结果: ╔════════════╦══════════╦══════════════╦═══════════╗ ║ Date ║ Employee ║ EmployeeType ║ Type ║ ╠════════════╬══════════╬══════════════╬═══════════╣ ║ 14/09/2015 ║ J
╔════════════╦══════════╦══════════════╦═══════════╗
║ Date ║ Employee ║ EmployeeType ║ Type ║
╠════════════╬══════════╬══════════════╬═══════════╣
║ 14/09/2015 ║ John ║ Permanent ║ Timesheet ║
║ 14/09/2015 ║ Silva ║ Permanent ║ Timesheet ║
║ 16/09/2015 ║ John ║ Permanent ║ Timesheet ║
║ 17/09/2015 ║ Airn ║ Casual ║ Timesheet ║
╚════════════╩══════════╩══════════════╩═══════════╝
如果该员工是“永久性”员工,并且如果该日期是“周一至周五”,我需要返回所有缺失的日期,如下所示:
╔════════════╦══════════╦══════════════╦═══════════╗
║ Date ║ Employee ║ EmployeeType ║ Type ║
╠════════════╬══════════╬══════════════╬═══════════╣
║ 14/09/2015 ║ John ║ Permanent ║ Timesheet ║
║ 14/09/2015 ║ Silva ║ Permanent ║ Timesheet ║
║ 15/09/2015 ║ John ║ Permanent ║ Missing ║
║ 15/09/2015 ║ Silva ║ Permanent ║ Missing ║
║ 16/09/2015 ║ John ║ Permanent ║ Timesheet ║
║ 16/09/2015 ║ Silva ║ Permanent ║ Missing ║
║ 17/09/2015 ║ John ║ Permanent ║ Missing ║
║ 17/09/2015 ║ Airn ║ Casual ║ Timesheet ║
║ 17/09/2015 ║ Silva ║ Permanent ║ Missing ║
║ 18/09/2015 ║ John ║ Permanent ║ Missing ║
║ 18/09/2015 ║ Silva ║ Permanent ║ Missing ║
╚════════════╩══════════╩══════════════╩═══════════╝
我不太了解SQL Server 2012中的LEAD命令。您可以使用a从@start和@end生成日期,并将其与表交叉连接以获取缺少的日期
WHERE子句
不考虑@@DATEFIRST,排除周末
E1,E2,E4,理货
对于这种类型的查询,我更喜欢使用永久表,而不是动态生成一组数字。日历表是日历的一种特殊情况
对于这个查询,在日历表中有一个日期和一个标志IsWeekday是很方便的。我的数据库中几乎没有其他字段,请参阅上面的链接了解更多详细信息和想法
CREATE TABLE [dbo].[Calendar](
[dt] [date] NOT NULL,
[IsWeekday] [bit] NOT NULL,
CONSTRAINT [PK_Calendar] PRIMARY KEY CLUSTERED
(
[dt] ASC
))
GO
-- Init calendar table with dates from 2000-01-01 till 2136-11-22 (50K rows)
INSERT INTO dbo.Calendar (dt, IsWeekday)
SELECT TOP (50000)
DATEADD(day, ROW_NUMBER() OVER (ORDER BY s1.[object_id])-1, '2000-01-01') AS dt
, 1 AS IsWeekday
FROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2
OPTION (MAXDOP 1);
-- Set IsWeekday flag
UPDATE dbo.Calendar
SET IsWeekday = 0
WHERE ((DATEPART(weekday, dt) + @@DATEFIRST) % 7) IN (0, 1);
现在我们准备好了。
我们将查找所有永久员工,并为给定范围内的每个永久员工生成一组工作日日期,然后将原始行左键联接到该日期。这一结果将与一组简单的非常任雇员联合起来
这是
如果雇员不是永久性的呢?如果此标准相关,请在样本数据中添加一两行非永久雇员类型,并向我们展示最终结果。添加@VladimirBaranov@FelixPamittan是的,没错。只有“永久雇员”才会显示丢失的时间表。只有从周一到周五,你的样本数据才是正确的?约翰·康瑟尔真的是同一个拥有永久雇员类型的约翰吗?@RogerOliveira,是的,请在数据中添加另一个永久雇员,只是为了澄清一下。此外,您是否希望在结果中看到John在2015年9月17日的记录?您的sql运行良好,但是,它还需要包括2015年9月17日的记录║ 艾恩║ 随便的║ 结果中的时间表。你能解释一下这部分吗?将E1N设置为从值1、1、1、1、1、1、1、1中选择1,请查看我的更新和解释链接。很好,我可以通过一些调整在存储过程中成功实现查询。。。谢谢,两种解决方案都很好。我希望我能把两者都定为最佳答案。
((DATEPART(dw, d.dt) + @@DATEFIRST) % 7) NOT IN (0, 1)
CREATE TABLE [dbo].[Calendar](
[dt] [date] NOT NULL,
[IsWeekday] [bit] NOT NULL,
CONSTRAINT [PK_Calendar] PRIMARY KEY CLUSTERED
(
[dt] ASC
))
GO
-- Init calendar table with dates from 2000-01-01 till 2136-11-22 (50K rows)
INSERT INTO dbo.Calendar (dt, IsWeekday)
SELECT TOP (50000)
DATEADD(day, ROW_NUMBER() OVER (ORDER BY s1.[object_id])-1, '2000-01-01') AS dt
, 1 AS IsWeekday
FROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2
OPTION (MAXDOP 1);
-- Set IsWeekday flag
UPDATE dbo.Calendar
SET IsWeekday = 0
WHERE ((DATEPART(weekday, dt) + @@DATEFIRST) % 7) IN (0, 1);
DECLARE @VarStartDate date = '2015-09-14';
DECLARE @VarEndDate date = '2015-09-20';
DECLARE @T TABLE (
dt date,
Employee nvarchar(50),
EmployeeType varchar(50),
Tp varchar(50));
INSERT INTO @T (dt, Employee, EmployeeType, Tp) VALUES
('2015-09-14', 'John' , 'Permanent', 'Timesheet'),
('2015-09-14', 'Silva', 'Permanent', 'Timesheet'),
('2015-09-16', 'John' , 'Permanent', 'Timesheet'),
('2015-09-17', 'Airn' , 'Casual' , 'Timesheet');
WITH
CTE_Employees
AS
(
SELECT DISTINCT Employee, EmployeeType
FROM @T
WHERE EmployeeType = 'Permanent'
)
,CTE_Dates
AS
(
SELECT
CTE_Employees.Employee
,CTE_Employees.EmployeeType
, dbo.Calendar.dt
FROM
CTE_Employees
CROSS JOIN dbo.Calendar
WHERE
dbo.Calendar.dt >= @VarStartDate AND
dbo.Calendar.dt <= @VarEndDate AND
dbo.Calendar.IsWeekday = 1
)
SELECT
CTE_Dates.dt
,CTE_Dates.Employee
,CTE_Dates.EmployeeType
,ISNULL(T.Tp, 'Missing') AS Tp
FROM
CTE_Dates
LEFT JOIN @T AS T ON
T.Employee = CTE_Dates.Employee AND
T.dt = CTE_Dates.dt
UNION ALL
SELECT
T.dt
,T.Employee
,T.EmployeeType
,T.Tp
FROM @T AS T
WHERE EmployeeType <> 'Permanent'
ORDER BY dt, Employee;
dt Employee EmployeeType Tp
2015-09-14 John Permanent Timesheet
2015-09-14 Silva Permanent Timesheet
2015-09-15 John Permanent Missing
2015-09-15 Silva Permanent Missing
2015-09-16 John Permanent Timesheet
2015-09-16 Silva Permanent Missing
2015-09-17 Airn Casual Timesheet
2015-09-17 John Permanent Missing
2015-09-17 Silva Permanent Missing
2015-09-18 John Permanent Missing
2015-09-18 Silva Permanent Missing