我有以下表格架构:
RecordId EmpID AbsCode DateFrom DateTo
---------------------------------------------------------------
666542 1511 AB 09/11/2011 10/11/2011
666986 1511 AB 11/11/2011 11/11/2011
666996 1511 EL 13/11/2011 17/11/2011
755485 1787 SL 01/11/2011 14/11/2011
758545 1787 SL 15/11/2011 26/11/2011
796956 1954 AB 09/11/2011 09/11/2011
799656 1367 AB 09/11/2011 09/11/2011
808845 1527 EL 16/11/2011 16/11/2011
823323 1527 EL 17/11/2011 17/11/2011
823669 1527 EL 18/11/2011 18/11/2011
899555 1123 AB 09/11/2011 09/11/2011
990990 1511 AB 12/11/2011 12/11/2011
如您所见,数据是为同一员工单独输入的。假设他报告SL(病假)一天,输入数据,然后他在第二天打电话报告另一天病假两天......等等。现在我想要的是在将这些条目呈现给客户端时合并这些条目,以便合并具有相同缺失代码的所有连续缺勤。例如,上面的表格应如下所示:
EmpID AbsCode DateFrom DateTo
-------------------------------------------------------------
1511 AB 09/11/2011 12/11/2011
1511 EL 13/11/2011 17/11/2011
1787 SL 01/11/2011 26/11/2011
1954 AB 09/11/2011 09/11/2011
1367 AB 09/11/2011 09/11/2011
1527 EL 16/11/2011 18/11/2011
1123 AB 09/11/2011 09/11/2011
我不是SQL人,我可以使用C#中的循环来迭代DataSet
或DataReader
,但我希望在存储过程中使用T-SQL执行此操作。我在StackOverFlow中发现了类似的问题并对它们进行了全部检查,它们都不适用于上面的示例表。
修改 有时我会遇到这样的情况:
RecordId EmpID AbsCode DateFrom DateTo
---------------------------------------------------------------
666542 1511 AB 09/11/2011 10/11/2011
666986 1511 AB 11/11/2011 25/12/2011
如您所见,此员工从2011年11月9日(d / M / yyyy)到(2011年12月25日)缺席,但客户要求从12月1日到12月31日有缺勤清单,所以结果应该是:
EmpID AbsCode DateFrom DateTo
-------------------------------------------------------------
1511 AB 01/12/2011 12/11/2011
基本上,它将根据提供的参数(from,to)显示结果。如果记录在请求的时间段之前盯着,它将显示它,但同时它将根据提供的参数显示记录的开始,同样适用于(from,to)参数之后的记录结尾。
答案 0 :(得分:1)
这将为您提供每位员工休息的天数。我认为他们希望在日期范围内看到这一点。您可以使用以下代码将varchars转换为日期:DATEDIFF(DAY, CONVERT(DATETIME,[DateFrom],103), CONVERT(DATETIME,[DateTo],103))
DECLARE @myTable TABLE
(
RecordId INT,
EmpID INT,
AbsCode VARCHAR(2),
DateFrom VARCHAR(12),
DateTo VARCHAR(12)
)
INSERT INTO @myTable
(
RecordId,
EmpID,
AbsCode,
DateFrom,
DateTo
)
SELECT 666542, 1511, 'AB', '09/11/2011', '10/11/2011' UNION ALL
SELECT 666986, 1511, 'AB', '11/11/2011', '11/11/2011' UNION ALL
SELECT 666996, 1511, 'EL', '13/11/2011', '17/11/2011' UNION ALL
SELECT 755485, 1787, 'SL', '01/11/2011', '14/11/2011' UNION ALL
SELECT 758545, 1787, 'SL', '15/11/2011', '26/11/2011' UNION ALL
SELECT 796956, 1954, 'AB', '09/11/2011', '09/11/2011' UNION ALL
SELECT 799656, 1367, 'AB', '09/11/2011', '09/11/2011' UNION ALL
SELECT 808845, 1527, 'EL', '16/11/2011', '16/11/2011' UNION ALL
SELECT 823323, 1527, 'EL', '17/11/2011', '17/11/2011' UNION ALL
SELECT 823669, 1527, 'EL', '18/11/2011', '18/11/2011' UNION ALL
SELECT 899555, 1123, 'AB', '09/11/2011', '09/11/2011' UNION ALL
SELECT 990990, 1511, 'AB', '12/11/2011', '12/11/2011'
SELECT [RecordId], [EmpID], [AbsCode], SUM(DAYS) NoDays
FROM
(
SELECT [RecordId], [EmpID], [AbsCode], DATEDIFF(DAY, CONVERT(DATETIME,[DateFrom],103), CONVERT(DATETIME,[DateTo],103)) Days
FROM @myTable
GROUP BY [RecordId], [EmpID], [AbsCode], DATEDIFF(DAY, CONVERT(DATETIME,[DateFrom],103), CONVERT(DATETIME,[DateTo],103))
) subQuery
GROUP BY [RecordId], [EmpID], [AbsCode]
答案 1 :(得分:1)
这是一个CTE所以它都需要一个一个地执行,但我会在我去的时候解释。
首先,我将设置我们感兴趣的日期范围的参数:
DECLARE @StartDate DateTime; SET @StartDate = '2011-11-01';
DECLARE @EndDate DateTime; SET @EndDate = '2011-11-30';
然后我会使用递归CTE将它们变成日期列表
WITH
ValidDates ( ValidDate ) AS
(
SELECT @StartDate
UNION ALL
SELECT DateAdd(day, 1, ValidDate)
FROM ValidDates
WHERE ValidDate < @EndDate
),
通过将其与原始记录中的范围相结合,我得到了个人缺席日期的列表。
使用row_number和datediff的组合我可以对连续日期进行分组。这假设没有重复。
DaysAbsent AS
(
SELECT
A.RecordID
, A.EmpID
, A.AbsCode
, DateDiff(Day, @StartDate, D.ValidDate)
- row_number()
over (partition by A.EmpID, A.AbsCode
order by D.ValidDate) AS DayGroup
, D.ValidDate AS AbsentDay
FROM
dbo.Absence A
INNER JOIN
ValidDates D
ON D.ValidDate >= DateFrom
and D.ValidDate <= DateTo
)
现在这是一个简单的选择,使用min和max将其重新调整为范围。
SELECT
EmpID
, AbsCode
, MIN(AbsentDay) AS DateFrom
, MAX(AbsentDay) AS DateTo
FROM
DaysAbsent
GROUP BY
EmpID
, AbsCode
, DayGroup
输出中不需要DayGroup,但分组需要DayGroup,否则非连续组将折叠成一个。
答案 2 :(得分:0)
Select EmpId, AbsCode, MIN(DateFrom) as DateFrom, MAX(DateTo) as DateTo From YOURTABLE
Group By EmpId, AbsCode