Sql server 从SQL Server 2012中的列表返回缺少的日期

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

考虑到过滤器:

开始日期:2015年9月14日星期一 完:2015年9月20日星期日 我从2009年14月至2009年20月的查询中得到了以下结果:

╔════════════╦══════════╦══════════════╦═══════════╗
║    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