考勤总结报告

Attendance summarized report

由于公司政策,我无法给出我正在处理的实际查询,但这里是细分和总体思路。我们有一个考勤登记簿,记录员工每天是否上班以及员工在哪里工作。我正在尝试对此进行总结,以说明该员工在该日期和该日期之间工作了 5 个班次。我遇到的问题是,一名特定员工在工作场所 A 工作了 2 天,然后被调到工作场所 B。在工作场所 B 工作几天后,该员工又被调回工作场所 A。

我的尝试结果表明,该员工从 1 月 1 日开始在工作场所 A 工作,到 1 月 10 日结束,只有 2 个工作班次。我在工作地点有一个分组,开始和结束日期是最小和最大选择。

SELECT att.Employee, att.Workplace, dte.BeginDate, dte.EndDate, shf.WorkShift FROM
(SELECT * FROM Attendance WHERE WorkDate BETWEEN '1-Jan' AND '30-Jan') att
CROSS APPLY (SELECT COUNT(Shift) WorkShift FROM Attendance WHERE WorkDate BETWEEN '1-Jan' AND '30-Jan' AND Employee = att.Employee AND WorkPlace = att.WorkPlace AND Shift = 'Worked') shf
CROSS APPLY (SELECT MAX(WorkDate) BeginDate, MIN(WorkDate) EndDate FROM Attendance WHERE WorkDate BETWEEN '1-Jan' AND '30-Jan' AND Employee = att.Employee AND WorkPlace = att.WorkPlace) dte

所以这个员工记录应该是这样的(很抱歉网格非常糟糕,我不知道如何让它看起来漂亮,非常欢迎您对其进行编辑以使其看起来更好)

| Name | Workplace  | beginDate | endDate | WorkShift |
| Jane | WorkPlaceA | 1-Jan     | 2-Jan   | 2         |
| Jane | WorkPlaceB | 3-Jan     | 8-Jan   | 5         |
| Jane | WorkPlaceA | 9-Jan     | 10-Jan  | 2         |

出席人数 table 看起来像这样

| Name | Workplace  |  Date  | Shift  |
| Jane | WorkplaceA |  1-Jan | Worked |
| Jane | WorkplaceA |  2-Jan | Worked |
| Jane | WorkplaceB |  3-Jan | Worked |
| Jane | WorkplaceB |  4-Jan | Worked |
| Jane | WorkplaceB |  5-Jan | Worked |
| Jane | WorkplaceA |  6-Jan | Absent |
| Jane | WorkplaceA |  7-Jan | Absent |
| Jane | WorkplaceA |  8-Jan | Worked |
| Jane | WorkplaceB |  9-Jan | Worked |
| Jane | WorkplaceB | 10-Jan | Worked |

我相信您可以使用 CTE 来完成此任务。这是显示您的预期值的示例工作代码。

;WITH CTE1 AS (
SELECT Employee, WorkPlace, TransactionDate,
    ROW_NUMBER() OVER(PARTITION BY WorkPlace ORDER BY TransactionDate) AS WP,
    ROW_NUMBER() OVER(ORDER BY TransactionDate) AS RN FROM Attendance WHERE Shift = 'Worked'),
    CTE2 AS (SELECT Employee, WorkPlace, TransactionDate, WP, RN, WP-RN AS GB FROM CTE1),
    CTE3 AS (SELECT Employee, WorkPlace, MIN(TransactionDate) AS TransactionDate, COUNT(1) AS Shifts FROM CTE2 GROUP BY Employee, WorkPlace, GB)

SELECT Employee, WorkPlace, TransactionDate AS [Start Date], DATEADD(DAY,Shifts - 1,TransactionDate) AS [End Date], Shifts FROM CTE3 ORDER BY TransactionDate ASC

我认为你给出的输出是错误的。

我认为你填充的方式 table 是错误的。

查看我的查询,可以进一步优化,不计缺席天数

declare @t table(Name varchar(100),Workplace varchar(100), AttnDate  date ,Shifts  varchar(100))
insert into @t values
('Jane','WorkplaceA',' 1-Jan-16','Worked')
,('Jane','WorkplaceA',' 2-Jan-16','Worked')
,('Jane','WorkplaceB',' 3-Jan-16','Worked')
,('Jane','WorkplaceB',' 4-Jan-16','Worked')
,('Jane','WorkplaceB',' 5-Jan-16','Worked')
,('Jane','WorkplaceA',' 6-Jan-16','Absent')
,('Jane','WorkplaceA',' 7-Jan-16','Absent')
,('Jane','WorkplaceA',' 8-Jan-16','Worked')
,('Jane','WorkplaceB',' 9-Jan-16','Worked')
,('Jane','WorkplaceB','10-Jan-16','Worked')

DECLARE @Name VARCHAR(100) = 'Jane'
DECLARE @FromDate DATE = '01-Jan-16'
DECLARE @ToDate DATE = '31-Jan-16';

WITH CTE
AS (
    SELECT *
        ,row_number() OVER (
            ORDER BY attndate
            ) rn
    FROM @t
    WHERE NAME = @Name
        AND (
            AttnDate BETWEEN @FromDate
                AND @ToDate
            )
    )
    ,CTE1
AS (
    SELECT A.NAME
        ,A.workplace
        ,A.AttnDate
        ,Shifts
        ,rn
        ,1 RN1
    FROM cte A
    WHERE rn = 1

    UNION ALL

    SELECT a.NAME
        ,a.workplace
        ,a.AttnDate
        ,a.Shifts
        ,CASE 
            WHEN a.workplace = b.workplace
                THEN b.rn
            ELSE b.rn + 1
            END rn
        ,RN1 + 1
    FROM CTE A
    INNER JOIN CTE1 b ON a.attndate > b.attndate
    WHERE a.rn = RN1 + 1
    )
    ,CTE2
AS (
    SELECT NAME
        ,Workplace
        ,AttnDate beginDate
        ,(
            SELECT max(AttnDate)
            FROM CTE1 b
            WHERE b.rn = a.rn
            ) endDate
        ,(
            SELECT count(*)
            FROM CTE1 b
            WHERE b.rn = a.rn
                AND Shifts = 'Worked'
            ) WorkShift
        ,rn
        ,ROW_NUMBER() OVER (
            PARTITION BY rn ORDER BY rn
            ) rn3
    FROM cte1 a
    )
SELECT NAME
    ,workplace
    ,beginDate
    ,endDate
    ,WorkShift
FROM cte2
WHERE rn3 = 1