繁体   English   中英

SQL Server 如何在组内创建组 - 使用 GROUP BY

[英]SQL Server How To make A Group Inside A Group - Using GROUP BY

我有一张表有这种结构

在此处输入图片说明

EmployeeID | LogDate | LogTime | TerminalID | InOut | Accepted

此表处理所有员工的考勤

其中 InOut Column = 0 --> In(员工只是打卡开始轮班)

其中 Inout Column = 1 --> Out(员工刚打完就结束他的班次)

我做出选择时的日期样本在此处输入图片说明

例如,上一张图片的 EmployeeID = 1009 在 2015-10-14 (06:56:28) 和 (16:13:51) 我需要在结果中给我他在这两次 2 次之间参加的时间即 (09:17:23)

我想要这个结果结构

EmployeeID | LogDate | NumberOfPunshings | State | HoursAttending

我试过这个查询

       select
Employeeid as EmpID,
logdate as logdt,
count(accepted) NumberOfPunshings,
case    count(accepted)                    WHEN 1 THEN 'No Out Punch'
                                           WHEN 2 THEN 'Perfect'
                                           Else 'Null'
                                           End as State,
CONVERT(varchar(12),
       DATEADD(minute,
       DATEDIFF(minute,
       (select top 1 LogTime from Accesslog where Inout=0),
       (select top 1 LogTime from Accesslog where InOut=1)), 0), 114) as HoursAttending

from Accesslog
where Logdate = CAST('2015-10-14' AS datetime)
group by
employeeid,logdate
order by Employeeid

但它不工作,因为我想要它只需要一个第一个值(表的)在 HoursAttending

在此处输入图片说明


我创建了 SQL Fiddle 来向您展示数据的外观

http://sqlfiddle.com/#!3/0152f9/1

EmpID |           logdt           |  NumberOfPunshings   |  State   |  HoursAttending

1009  | October, 14 2015 00:00:00 |          2           | Perfect  |   08:00:00:000
1088  | October, 15 2015 00:00:00 |          2           | Perfect  |   08:00:00:000

预期结果必须是

EmpID |           logdt           |  NumberOfPunshings   |  State   |  HoursAttending

1009  | October, 14 2015 00:00:00 |          2           | Perfect  |   08:00:00:000
1088  | October, 15 2015 00:00:00 |          2           | Perfect  |   06:00:00:000

这些表在 HoursAttending 列中的差异是因为

第一个员工 (1009) 从 08:00 到 16:00 开始工作,所以持续时间是 (08:00) 正确。

第二个员工 (1088) 从 009:00 到 15:00 开始工作,所以持续时间必须是 (06:00) 而不是 (08:00) 正确。

想象一下,如果我们可以轻松获取数据,并且我们清楚地了解预期的最终结果应该是什么样子,将会发生什么。

SQL小提琴

MS SQL Server 2014 架构设置

CREATE TABLE Accesslog
    ([EmployeeID] int, [LogDate] datetime, [LogTime] datetime, [Terminal] varchar(11), [InOut] int, [Accepted] int)
;

INSERT INTO Accesslog
    ([EmployeeID], [LogDate], [LogTime], [Terminal], [InOut], [Accepted])
VALUES
    (1009, '2015-10-14 00:00:00', '1900-01-01 06:36:06', 'abcdedghijk', 0, 1),
    (1009, '2015-10-14 00:00:00', '1900-01-01 16:22:41', 'abcdedghijk', 1, 1)
;

查询 1

select
        EmployeeID
      , LogDate
      , MIN(case when InOut = 0 then cast(LogTime as time) end) as LogTimeMin
      , MAX(case when InOut = 1 then cast(LogTime as time) end) as LogTimeMax
      , COUNT(*) as CountPunches
      , CONVERT(varchar(12),
         DATEADD(minute,
         DATEDIFF(minute,
         MIN(case when InOut = 0 then cast(LogTime as time) end),
         MAX(case when InOut = 1 then cast(LogTime as time) end)), 0), 114) as HoursAttending
from Accesslog
group by
        EmployeeID
      , LogDate

结果

| EmployeeID |          LogDate |  LogTimeMin |  LogTimeMax | CountPunches | HoursAttending |
|------------|------------------|-------------|-------------|--------------|----------------|
|       1009 | October, 14 2015 | 06:36:06.00 | 16:22:41.00 |            2 |   09:46:00:000 |

第2部分

要解决轮班问题,请尝试以下操作。 请注意,如果您然后每天只需要一行,也可以使用 group by 查询,但将下面看到的查询变成“派生表”(子查询)

SQL小提琴

MS SQL Server 2014 架构设置

CREATE TABLE Accesslog
    ([EmployeeID] int, [LogDate] datetime, [LogTime] datetime, [Terminal] varchar(11), [InOut] int, [Accepted] int)
;

INSERT INTO Accesslog
    ([EmployeeID], [LogDate], [LogTime], [Terminal], [InOut], [Accepted])
VALUES
    (1209, '2015-10-14 00:00:00', '1900-01-01 07:00:00', 'abcdedghijk', 0, 1),
    (1209, '2015-10-14 00:00:00', '1900-01-01 12:01:00', 'abcdedghijk', 1, 1),
    (1209, '2015-10-14 00:00:00', '1900-01-01 15:00:00', 'abcdedghijk', 0, 1),
    (1209, '2015-10-14 00:00:00', '1900-01-01 20:02:00', 'abcdedghijk', 1, 1),
    (1009, '2015-10-14 00:00:00', '1900-01-01 08:00:00', 'abcdedghijk', 0, 1),
    (1009, '2015-10-14 00:00:00', '1900-01-01 16:00:00', 'abcdedghijk', 1, 1),
    (1088, '2015-10-15 00:00:00', '1900-01-01 09:00:00', 'aaaa', 0, 1),
    (1088, '2015-10-15 00:00:00', '1900-01-01 15:00:00', 'aaaa', 1, 1)
;

查询 1

/*
 including (07:00 - 12:00) shift two (15:00 - 20:00) 
 */

WITH CTE as (
        SELECT *, ROW_NUMBER() OVER(PARTITION BY EmployeeID, LogDate, InOut
                                    ORDER BY LogTime ASC) AS shiftno
        FROM Accesslog
             )
SELECT
        ins.EmployeeID
      , ins.LogDate
      , ins.LogTime  as LogTimeIn
      , outs.LogTime as LogTimeOut
      , ins.Accepted + ISNULL(outs.Accepted,0) as CountPunches
      , CONVERT(varchar(12),
         DATEADD(minute,
         DATEDIFF(minute,
         ins.LogTime,
         outs.LogTime), 0), 114) as HoursAttending
FROM CTE  AS ins
INNER JOIN CTE AS outs ON ins.InOut = 0 AND outs.InOut = 1
                      AND ins.EmployeeID = outs.EmployeeID
                      AND ins.LogDate = outs.LogDate
                      AND ins.shiftno = outs.shiftno

结果

| EmployeeID |                   LogDate |                 LogTimeIn |                LogTimeOut | CountPunches | HoursAttending |
|------------|---------------------------|---------------------------|---------------------------|--------------|----------------|
|       1009 | October, 14 2015 00:00:00 | January, 01 1900 08:00:00 | January, 01 1900 16:00:00 |            2 |   08:00:00:000 |
|       1088 | October, 15 2015 00:00:00 | January, 01 1900 09:00:00 | January, 01 1900 15:00:00 |            2 |   06:00:00:000 |
|       1209 | October, 14 2015 00:00:00 | January, 01 1900 07:00:00 | January, 01 1900 12:01:00 |            2 |   05:01:00:000 |
|       1209 | October, 14 2015 00:00:00 | January, 01 1900 15:00:00 | January, 01 1900 20:02:00 |            2 |   05:02:00:000 |

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM