【发布时间】:2019-11-25 05:40:26
【问题描述】:
我有以下示例数据:
--Table 1:
CREATE TABLE tbl_Emp_1
(
EmpID INT,
ColDate DATE
);
INSERT INTO tbl_Emp_1 VALUES(1,'2019-11-01');
INSERT INTO tbl_Emp_1 VALUES(2,'2019-11-02');
INSERT INTO tbl_Emp_1 VALUES(3,'2019-11-11');
INSERT INTO tbl_Emp_1 VALUES(4,'2019-11-12');
INSERT INTO tbl_Emp_1 VALUES(9,'2019-11-13');
INSERT INTO tbl_Emp_1 VALUES(6,'2019-11-16');
INSERT INTO tbl_Emp_1 VALUES(408,'2019-11-25');
--Table 2:
CREATE TABLE tbl_Emp_2
(
EmpID INT,
ColDate DATE
);
INSERT INTO tbl_Emp_2 VALUES(11,'2019-11-02');
INSERT INTO tbl_Emp_2 VALUES(22,'2019-11-06');
INSERT INTO tbl_Emp_2 VALUES(22,'2019-11-08');
INSERT INTO tbl_Emp_2 VALUES(33,'2019-11-10');
INSERT INTO tbl_Emp_2 VALUES(44,'2019-11-15');
--Table 3:
CREATE TABLE tbl_Emp_3
(
EmpID INT,
ColDate DATE
);
INSERT INTO tbl_Emp_3 VALUES(111,'2019-11-12');
INSERT INTO tbl_Emp_3 VALUES(222,'2019-11-16');
INSERT INTO tbl_Emp_3 VALUES(333,'2019-11-17');
INSERT INTO tbl_Emp_3 VALUES(444,'2019-11-19');
INSERT INTO tbl_Emp_3 VALUES(5,'2019-11-22');
--现在我将创建这些表的视图。
CREATE VIEW vw_Emp AS
SELECT *,1 AS TableID FROM tbl_Emp_1
UNION ALL
SELECT *,2 AS TableID FROM tbl_Emp_2
UNION ALL
SELECT *,3 AS TableID FROM tbl_Emp_3;
预期输出:
EmpID ColDate
--------------------------------
2 2019-11-02 ---TABLE 1 Starts
NULL 2019-11-03 - 2019-11-10
3 2019-11-11
9 2019-11-13
NULL 2019-11-14 - 2019-11-15
6 2019-11-16
NULL 2019-11-17 - 2019-11-24
408 2019-11-25
11 2019-11-02 ---TABLE 2 Data Starts
NULL 2019-11-03 - 2019-11-05
22 2019-11-06
NULL 2019-11-07
22 2019-11-08
NULL 2019-11-09
33 2019-11-10
NULL 2019-11-11 - 2019-11-14
44 2019-11-15
111 2019-11-12 ---TABLE 3 Data Starts
NULL 2019-11-13 - 2019-11-15
222 2019-11-16
333 2019-11-17
NULL 2019-11-18
444 2019-11-19
NULL 2019-11-20 - 2019-11-21
5 2019-11-22
关于输出:显示Employee的缺勤日期,并显示该日期前后一个日期的emp数据(员工不存在日期)。
我的尝试:
DECLARE @TableID INT,
@MinDate DATE,
@MaxDate DATE;
DECLARE Cur_Get_MinMax1 CURSOR FOR
SELECT TableID,
(SELECT MIN(ColDate) FROM vw_Emp WHERE TableID = v1.TableID),
(SELECT MAX(ColDate) FROM vw_Emp WHERE TableID = v1.TableID)
FROM vw_Emp v1
GROUP BY TableID;
IF OBJECT_ID('tempdb..#TempEmpData') IS NOT NULL
DROP TABLE #TempEmpData;
CREATE TABLE #TempEmpData
(
Dates DATE,
TableID int
);
OPEN Cur_Get_MinMax1;
FETCH NEXT FROM Cur_Get_MinMax1 INTO
@TableID,
@MinDate,
@MaxDate;
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT(@TableID);
PRINT(@MinDate);
PRINT(@MaxDate);
INSERT INTO #TempEmpData
SELECT TOP (DATEDIFF(DAY, @MinDate, @MaxDate) + 1)
Date = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @MinDate),
@TableID
FROM sys.all_objects a
CROSS JOIN sys.all_objects b
FETCH NEXT FROM Cur_Get_MinMax1 INTO
@TableID,
@MinDate,
@MaxDate;
END;
CLOSE Cur_Get_MinMax1;
DEALLOCATE Cur_Get_MinMax1;
查询一:
SELECT v.EmpID,t.Dates
FROM #TempEmpData t
LEFT JOIN vw_Emp v ON v.ColDate = t.Dates AND v.TableID = t.TableID
ORDER BY t.TableID,t.Dates;
编辑:
查询2:
;WITH CTE AS
(
SELECT DISTINCT TableID,Dates,EmpID,
coalesce(stuff((select distinct CAST(MIN(Dates) as varchar(10))+'~'+ CAST(MAX(Dates) as varchar(10)) from #TempEmpData t1 where a.rr = 1 AND t1.Dates=a.Dates for xml path('')),1,0,''),cast(Dates as varchar(10))) Coldate
FROM
(
SELECT v.EmpID,
t.Dates,
t.TableID,
RANK() OVER(ORDER BY v.EmpID) rr
FROM vw_Emp v
RIGHT JOIN #TempEmpData t ON v.ColDate = t.Dates AND v.TableID = t.TableID
GROUP BY t.TableID,v.EmpID,t.Dates,v.TableID
) a
)
SELECT EmpID,ColDate
FROM CTE
ORDER BY TableID,Dates
【问题讨论】:
-
很高兴您将示例数据发布为 DDL+DML,但您的问题仍然不是很清楚。
-
@ZoharPeled,我想显示员工数据及其存在和缺席日期。如果员工连续缺勤超过 1 天,则应显示
FromDate to ToDate和null EmpID。并且还想用empID显示当前日期的前后一天。 -
很抱歉,但我看不出显示没有员工 ID 的日期的意义。这并不能告诉您哪个员工缺席......另外,3 个表结构可能应该是一个表,但这是另一回事。
-
@ZoharPeled,实际上缺勤日期不会有员工ID,所以我们只需要获取没有任何员工数据的日期。只有员工的日期在场,我们需要首先在每个表的
MIN(ColDate)和MAX(ColDate)之间获取所有这些日期,并找出缺失的日期。如果我仍然无法描述它,我深表歉意。 -
抱歉,您是要获取三明治信息吗?像假期前后缺席那样会造成假期的三明治吗?这是你想要的输出吗?
标签: sql-server tsql sql-server-2012