如何使此代码在SQL Server 2016中可重用(Union all除外)

如何使此代码在SQL Server 2016中可重用(Union all除外),sql,sql-server,sql-server-2012,Sql,Sql Server,Sql Server 2012,我正在尝试捕捉过去的数据。假设今天在员工表中,当我抓拍时,我可以看到1000名员工计数。但昨天的情况并非如此。今天有2名新员工加入,因此我得到了1000份。如果我想拍昨天的快照,我应该在过去的60天里拍998安等 我已经试过了。但这在更多的日子里是没有用的 /* Create Table */ CREATE TABLE dbo.EMPTable (ID INT, H_Date DATE) /* Load Data */ INSERT INTO dbo.EMPTable VALUES (1,'

我正在尝试捕捉过去的数据。假设今天在员工表中,当我抓拍时,我可以看到1000名员工计数。但昨天的情况并非如此。今天有2名新员工加入,因此我得到了1000份。如果我想拍昨天的快照,我应该在过去的60天里拍998安等

我已经试过了。但这在更多的日子里是没有用的

/* Create Table */

CREATE TABLE dbo.EMPTable (ID INT, H_Date DATE)

/* Load Data */
INSERT INTO dbo.EMPTable VALUES (1,'2019-04-17')
INSERT INTO dbo.EMPTable VALUES (2,'2019-04-17')
INSERT INTO dbo.EMPTable VALUES (3,'2019-04-16')
INSERT INTO dbo.EMPTable VALUES (4,'2019-04-16')
INSERT INTO dbo.EMPTable VALUES (5,'2019-04-15')
INSERT INTO dbo.EMPTable VALUES (6,'2019-04-15')
INSERT INTO dbo.EMPTable VALUES (7,'2019-04-15')
INSERT INTO dbo.EMPTable VALUES (8,'2019-04-14')
INSERT INTO dbo.EMPTable VALUES (9,'2019-04-14')
INSERT INTO dbo.EMPTable VALUES (10,'2019-04-14')
INSERT INTO dbo.EMPTable VALUES (11,'2019-04-14')
INSERT INTO dbo.EMPTable VALUES (12,'2019-04-14')
INSERT INTO dbo.EMPTable VALUES (13,'2019-04-13')
INSERT INTO dbo.EMPTable VALUES (14,'2019-04-13')
INSERT INTO dbo.EMPTable VALUES (15,'2019-04-13')
INSERT INTO dbo.EMPTable VALUES (16,'2019-04-13')
INSERT INTO dbo.EMPTable VALUES (17,'2019-04-13')
INSERT INTO dbo.EMPTable VALUES (16,'2019-04-11')
INSERT INTO dbo.EMPTable VALUES (17,'2019-04-11')

--SELECT * FROM dbo.EMPTable

/* Long query */
SELECT 
CAST(GETDATE()-6 AS DATE) AS Snap_Date, 
COUNT(ID) AS I_Count
FROM dbo.EMPTable
WHERE H_Date >=CAST((GETDATE()-6) -3 AS DATE) AND H_Date <= CAST((GETDATE()-6)  AS DATE)
UNION ALL
SELECT 
CAST(GETDATE()-5 AS DATE) AS Snap_Date, 
COUNT(ID) AS I_Count
FROM dbo.EMPTable
WHERE H_Date >=CAST((GETDATE()-5)  -3 AS DATE) AND H_Date <= CAST((GETDATE()-5)  AS DATE)
UNION ALL
SELECT 
CAST(GETDATE()-4 AS DATE) AS Snap_Date, 
COUNT(ID) AS I_Count
FROM dbo.EMPTable
WHERE H_Date >=CAST((GETDATE()-4) -3 AS DATE) AND H_Date <= CAST((GETDATE()-4)  AS DATE)
UNION ALL
SELECT 
CAST(GETDATE()-3 AS DATE) AS Snap_Date, 
COUNT(ID) AS I_Count
FROM dbo.EMPTable
WHERE H_Date >=CAST((GETDATE()-3)  -3 AS DATE) AND H_Date <= CAST((GETDATE()-3)  AS DATE)
UNION ALL
SELECT 
CAST(GETDATE()-2 AS DATE) AS Snap_Date, 
COUNT(ID) AS I_Count
FROM dbo.EMPTable
WHERE H_Date >=CAST((GETDATE()-2)  -3 AS DATE) AND H_Date <= CAST((GETDATE()-2)  AS DATE)
UNION ALL
SELECT 
CAST(GETDATE()-1 AS DATE) AS Snap_Date, 
COUNT(ID) AS I_Count
FROM dbo.EMPTable
WHERE H_Date >=CAST((GETDATE()-1)  -3 AS DATE) AND H_Date <= CAST((GETDATE()-1)  AS DATE)
UNION ALL
SELECT 
CAST(GETDATE() AS DATE) AS Snap_Date, 
COUNT(ID) AS I_Count
FROM dbo.EMPTable
WHERE H_Date >=CAST((GETDATE())  -3 AS DATE)
--------------------------
Expected Result
--------------------------
Snap_Date   I_Count
2019-04-11  2
2019-04-12  2
2019-04-13  7
2019-04-14  12
2019-04-15  13
2019-04-16  15
2019-04-17  12


如果你现在看到了,从今天开始的最后三天我都在拍快照。从昨天开始的最后三天再次来到昨天,以此类推。 此外,我们不能将H_日期作为Snap_日期,因为如果其中一个日期没有雇佣员工,该怎么办。比如,2019年4月12日,没有雇佣任何员工。那么,将H_日期作为Snap_日期时,该特定日期将不可用


我道歉。根据我看到的解决方案,我不清楚我代表的是完整的问题陈述。希望现在一切都清楚了。

嗯,老实说,我不完全理解你的帖子。但是,为了从给定的示例数据中获得预期结果,您可以将具有更早或相等h_日期的记录加入到一组不同的h_日期中,然后按日期分组并进行计数

SELECT e1.h_date snap_date,
       coalesce(count(*), 0) i_count
       FROM (SELECT DISTINCT
                    e1.h_date
                    FROM emptable e1) e1
            INNER JOIN emptable e2
                       ON e2.h_date <= e1.h_date
       GROUP BY e1.h_date;
根据需要更改开始日期和返回天数


嗯,说实话,我不完全理解你的帖子。但是,为了从给定的示例数据中获得预期结果,您可以将具有更早或相等h_日期的记录加入到一组不同的h_日期中,然后按日期分组并进行计数

SELECT e1.h_date snap_date,
       coalesce(count(*), 0) i_count
       FROM (SELECT DISTINCT
                    e1.h_date
                    FROM emptable e1) e1
            INNER JOIN emptable e2
                       ON e2.h_date <= e1.h_date
       GROUP BY e1.h_date;
根据需要更改开始日期和返回天数


首先创建一个日历表,其中包含足够大的日期范围,以满足未来的需要

CREATE TABLE dbo.Calendar (Date DATE PRIMARY KEY)

--2010-01-01 TO 2039-12-31 inclusive. Adjust as needed
INSERT INTO dbo.Calendar
SELECT TOP (10957) DATEADD(DAY, ROW_NUMBER() OVER (ORDER BY @@SPID), '2009-12-31')
FROM sys.all_objects o1, sys.all_objects o2;
然后,您可以将其外部连接到上面,以获得缺少的日期,如下所示

SELECT C.Date, 
       SUM(COUNT(E.ID))  OVER (ORDER BY C.Date ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS I_Count
FROM dbo.Calendar C
LEFT JOIN dbo.EMPTable E ON E.H_Date = C.Date
WHERE C.Date BETWEEN '2019-04-11' AND CAST(GETDATE() AS DATE)
GROUP  BY C.Date
这方面的执行计划相当有效。以下示例,索引为dbo.EMPTableH_Date INCLUDEID


首先创建一个日历表,其中包含足够大的日期范围,以满足未来的需要

CREATE TABLE dbo.Calendar (Date DATE PRIMARY KEY)

--2010-01-01 TO 2039-12-31 inclusive. Adjust as needed
INSERT INTO dbo.Calendar
SELECT TOP (10957) DATEADD(DAY, ROW_NUMBER() OVER (ORDER BY @@SPID), '2009-12-31')
FROM sys.all_objects o1, sys.all_objects o2;
然后,您可以将其外部连接到上面,以获得缺少的日期,如下所示

SELECT C.Date, 
       SUM(COUNT(E.ID))  OVER (ORDER BY C.Date ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS I_Count
FROM dbo.Calendar C
LEFT JOIN dbo.EMPTable E ON E.H_Date = C.Date
WHERE C.Date BETWEEN '2019-04-11' AND CAST(GETDATE() AS DATE)
GROUP  BY C.Date
这方面的执行计划相当有效。以下示例,索引为dbo.EMPTableH_Date INCLUDEID


我完全推荐第二个,而不是第一个。我会添加一个统计表,这样我们就可以在没有新员工的日子里显示结果。@LuisCazares-是的,第二个有一些性能优势。它可以使用按H_Date排序的输入来进行分组和运行合计,而无需添加任何额外的区分步骤,并且前面的无边界行比2012年的默认范围更有效too@Piotr-无需使用评论来告诉我们您将做什么。有一个应答器。你可以添加一个答案。如果这是一个提示,让我这样做,那么它将不会被视为我完成了一天,所以@我向你道歉。我不清楚我的问题陈述。我没有考虑所有可能的情况。我现在已经补充了。我完全推荐第二个,而不是第一个。我会添加一个统计表,这样我们就可以在没有新员工的日子里显示结果。@LuisCazares-是的,第二个有一些性能优势。它可以使用按H_Date排序的输入来进行分组和运行合计,而无需添加任何额外的区分步骤,并且前面的无边界行比2012年的默认范围更有效too@Piotr-无需使用评论来告诉我们您将做什么。有一个应答器。你可以添加一个答案。如果这是一个提示,让我这样做,那么它将不会被视为我完成了一天,所以@我向你道歉。我不清楚我的问题陈述。我没有考虑所有可能的情况。我现在已经补充了。如果你现在看到的话,我将在从今天开始的最后三天内拍摄快照。从昨天开始的最后三天再次来到昨天,以此类推。此外,我们不能将H_日期作为Snap_日期,因为如果其中一个日期没有雇佣员工,该怎么办。比如,2019年4月12日,没有雇佣任何员工。那么,将H_日期作为Snap_日期时,该特定日期将不可用。我道歉。根据我看到的解决方案,我不清楚我代表的是完整的问题陈述。希望现在一切都清楚了。@PKernel:我回答中的第二个问题已经解决了数据丢失几天的问题。如果你现在看到了,我将从今天开始拍摄最后三天的快照。从昨天开始的最后三天再次来到昨天,以此类推。此外,我们不能将H_日期作为Snap_日期,因为如果其中一个日期没有雇佣员工,该怎么办。比如,2019年4月12日,没有雇佣任何员工。那么,将H_日期作为Snap_日期时,该特定日期将不可用。我道歉。根据我看到的解决方案,我不清楚我代表的是完整的问题陈述。希望现在一切都清楚了。@PKernel:我答案中的第二个查询已经解决了数据丢失几天的问题。请从SELECT DISTI中选择e1.h_date snap_date,COALEASECUNT*,0 i_count 日历e1中的NCT日期作为h_日期,其中e1.date>=CASTGETDATE-6作为日期和e1.date选择e1.h_日期捕捉日期,合并计数*,0 i_计数从日历e1中选择不同日期作为h_日期,其中e1.date>=CASTGETDATE-6作为日期和e1.date