Sql 查询计算工作时间
我有一个查询,get的员工打卡上班/下班,并将他们分组为夜班,因此第一个记录是前一个晚上 此查询的结果如下所示Sql 查询计算工作时间,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我有一个查询,get的员工打卡上班/下班,并将他们分组为夜班,因此第一个记录是前一个晚上 此查询的结果如下所示 Name ID CardCode Telephone EndOverDay T Day DayNumber InDay Name Pen-005731 0042f55c 8 1 2015-11-02 19:42:12.000 2
Name ID CardCode Telephone EndOverDay T Day DayNumber InDay
Name Pen-005731 0042f55c 8 1 2015-11-02 19:42:12.000 2015.11.02 42309 1
Name Pen-005731 0042f55c 8 1 2015-11-03 01:12:08.000 2015.11.03 42309 2
Name Pen-005731 0042f55c 8 1 2015-11-03 01:41:43.000 2015.11.03 42309 3
Name Pen-005731 0042f55c 8 1 2015-11-03 07:47:25.000 2015.11.03 42309 4
Name Pen-005731 0042f55c 8 1 2015-11-03 19:44:02.000 2015.11.03 42310 1
Name Pen-005731 0042f55c 8 1 2015-11-04 01:00:01.000 2015.11.04 42310 2
Name Pen-005731 0042f55c 8 1 2015-11-04 01:26:30.000 2015.11.04 42310 3
Name Pen-005731 0042f55c 8 1 2015-11-04 07:55:55.000 2015.11.04 42310 4
Name Pen-005731 0042f55c 8 1 2015-11-04 19:42:51.000 2015.11.04 42311 1
Name Pen-005731 0042f55c 8 1 2015-11-05 01:08:35.000 2015.11.05 42311 2
Name Pen-005731 0042f55c 8 1 2015-11-05 01:36:20.000 2015.11.05 42311 3
Name Pen-005731 0042f55c 8 1 2015-11-05 07:49:14.000 2015.11.05 42311 4
Name Pen-005731 0042f55c 8 1 2015-11-05 19:42:37.000 2015.11.05 42312 1
Name Pen-005731 0042f55c 8 1 2015-11-06 01:17:05.000 2015.11.06 42312 2
Name Pen-005731 0042f55c 8 1 2015-11-06 01:45:44.000 2015.11.06 42312 3
Name Pen-005731 0042f55c 8 1 2015-11-06 07:45:56.000 2015.11.06 42312 4
Name Pen-005731 0042f55c 8 1 2015-11-09 19:39:21.000 2015.11.09 42316 1
Name Pen-005731 0042f55c 8 1 2015-11-10 01:11:15.000 2015.11.10 42316 2
Name Pen-005731 0042f55c 8 1 2015-11-10 01:36:39.000 2015.11.10 42316 3
Name Pen-005731 0042f55c 8 1 2015-11-10 07:57:02.000 2015.11.10 42316 4
Name Pen-005731 0042f55c 8 1 2015-11-10 19:42:45.000 2015.11.10 42317 1
Name Pen-005731 0042f55c 8 1 2015-11-11 01:16:07.000 2015.11.11 42317 2
Name Pen-005731 0042f55c 8 1 2015-11-11 01:40:06.000 2015.11.11 42317 3
Name Pen-005731 0042f55c 8 1 2015-11-11 07:55:20.000 2015.11.11 42317 4
T是记录的时间日期
Inday是刷卡的顺序
我需要得到每个DayNumber的时间,所以对于DayNumber 42317
这将是第1天和第2天,然后是第3-4天,再加上总时间的Datediff
这是我到目前为止所拥有的
WITH ByDays AS (
SELECT CHINA_VISION_PubPersonnel.Name, CHINA_VISION_PubPersonnel.ID, CHINA_VISION_PubCards.CardCode, CHINA_VISION_PubPersonnel.Telephone, ATDShiftDetail.EndOverDay,
CHINA_VISION_DorEvents.EventTM AS T, CONVERT(VARCHAR(10), CHINA_VISION_DorEvents.EventTM, 102) AS Day,
FLOOR(CONVERT(FLOAT, DATEADD(hour, 5, EventTM))) AS DayNumber,
ROW_NUMBER() OVER(PARTITION BY FLOOR(CONVERT(FLOAT,FLOOR(CONVERT(FLOAT, DATEADD(hour, 6, EventTM))))) ORDER BY FLOOR(CONVERT(FLOAT, DATEADD(hour, 5, EventTM)))) InDay
FROM CHINA_VISION_PubCards INNER JOIN
CHINA_VISION_PubPersonnel ON CHINA_VISION_PubCards.PubPersonnel_Ref = CHINA_VISION_PubPersonnel.Reference INNER JOIN
CHINA_VISION_DorEvents ON CHINA_VISION_PubCards.CardCode = CHINA_VISION_DorEvents.CardCode INNER JOIN
ATDShiftDetail ON RIGHT(CHINA_VISION_PubPersonnel.ID, 4) = ATDShiftDetail.Name
WHERE (CHINA_VISION_DorEvents.DorCtrls_Ref = '16') AND (CHINA_VISION_DorEvents.CardCode = '0042f55c') AND (CONVERT(Date, CHINA_VISION_DorEvents.EventTM)
> DATEADD(day,-10, GETDATE())) AND ATDShiftDetail.EndOverDay = '1'
)
, Diffs AS (
SELECT
EvenRow.Day,EvenRow.DayNumber, OddRow.ID, OddRow.name , OddRow.CardCode , OddRow.Telephone ,EvenRow.EndOverDay ,
EvenRow.T ET, OddRow.T OT, OddRow.T-EvenRow.T Diff,
DATEDIFF(S,EvenRow.T,OddRow.T) DiffSeconds -- difference in seconds
FROM
(SELECT BE.T, BE.Day, BE.InDay, BE.ID , BE.Name , Be.CardCode, BE.Telephone, BE.EndOverDay, BE.DayNumber
FROM ByDays BE) EvenRow -- Even rows
INNER JOIN
(SELECT BO.T, BO.Day, BO.InDay , BO.ID , BO.Name , BO.CardCode, BO.Telephone, BO.EndOverDay
FROM ByDays BO) OddRow -- Odd rows
ON EvenRow.InDay = OddRow.InDay +1 -- Join rows (1,2), (3,4) and so on
AND EvenRow.Day = OddRow.Day -- in the same day
)
SELECT
Name,
CardCode,
ID,
Telephone,
EndOverDay,
MIN(Day),
DayNumber,
SUM(DiffSeconds) Seconds,
CONVERT(VARCHAR(8),
(DATEADD(S, SUM(DiffSeconds), '1900-01-01T00:00:00')),
108) TotalHHMMSS -- The same, formatted as HH:MM:SS
FROM Diffs GROUP BY DayNumber, ID , CardCode, Name, Telephone,EndOverDay
ORDER BY DayNumber
这会产生这样的结果
Name CardCode ID Telephone EndOverDay Day DayNumber Seconds TotalHHMMSS
Name 0042f55c Pen-005731 8 1 2015.11.03 42309 42997 11:56:37
Name 0042f55c Pen-005731 8 1 2015.11.04 42310 42416 11:46:56
Name 0042f55c Pen-005731 8 1 2015.11.05 42311 42803 11:53:23
Name 0042f55c Pen-005731 8 1 2015.11.06 42312 -23331 17:31:09
Name 0042f55c Pen-005731 8 1 2015.11.10 42316 42343 11:45:43
Name 0042f55c Pen-005731 8 1 2015.11.11 42317 -23953 17:20:47
正如您所看到的,由于提供的数据的结果不正确,因此没有对正确的时间进行差异化处理
create table punch (
Name nvarchar(50),
Id nvarchar(50),
CardCode nvarchar(50),
TelephoneEnd int,
OverDay int,
T datetime,
punchDate datetime,
DayNumber int,
InDay int )
insert into punch
select 'Hame', 'Pen-005731', '0042f55c', 8, 1, '2015-11-09 19:39:21.000', '2015.11.09', 42316, 1 union all
select 'Hame', 'Pen-005731', '0042f55c', 8, 1, '2015-11-10 01:11:15.000', '2015.11.10', 42316, 2 union all
select 'Hame', 'Pen-005731', '0042f55c', 8, 1, '2015-11-10 01:36:39.000', '2015.11.10', 42316, 3 union all
select 'Hame', 'Pen-005731', '0042f55c', 8, 1, '2015-11-10 07:57:02.000', '2015.11.10', 42316, 4 union all
select 'Hame', 'Pen-005731', '0042f55c', 8, 1, '2015-11-10 19:42:45.000', '2015.11.10', 42317, 1 union all
select 'Hame', 'Pen-005731', '0042f55c', 8, 1, '2015-11-11 01:16:07.000', '2015.11.11', 42317, 2 union all
select 'Hame', 'Pen-005731', '0042f55c', 8, 1, '2015-11-11 01:40:06.000', '2015.11.11', 42317, 3 union all
select 'Hame', 'Pen-005731', '0042f55c', 8, 1, '2015-11-11 07:55:20.000', '2015.11.11', 42317, 4
select sum(x.minutesPunched)/60 as hoursWorked,
sum(x.minutesPunched) % 60 as minutesWorked
from (
select datediff(mi, p2.T, p1.T) as minutesPunched
from punch p1
inner join punch p2 on p1.DayNumber = p2.DayNumber and p1.InDay = p2.InDay + 1
) x
通过删除2-3个AGG进行分组:
select sum(x.minutesPunched)/60 as hoursWorked,
sum(x.minutesPunched) % 60 as minutesWorked,
x.DayNumber
from (
select datediff(mi, p1.T, p2.T) as minutesPunched,
p1.DayNumber
from punch p1
inner join punch p2 on p1.DayNumber = p2.DayNumber and p1.InDay = p2.InDay - 1
where (p1.InDay + 1) % 2 = 0
) x
group by x.DayNumber
您说过,您有一个查询,请与我们共享(使用相关的表和一些示例数据)。创建一个数据库也有助于我们更好地了解您的问题。在提问之前,请阅读并使用,以确保您的问题不是重复的。您获得此数据集并在InDay=InDay+1上加入自身。这会在同一行上显示日期时间。然后您只需对其进行datediff。允许您对表进行更改吗?InDay与打卡/打卡的关系毫无意义。如果有一个名为clockOut的额外时间列,然后将T重命名为clockIn,会容易得多。由于无法更改表格,数据来自刷卡系统嗨,谢谢,我认为这会起作用,但我每天需要一个单独的工作时间,而不是所有天的总和,我该怎么做?谢谢ewahner,还有一件事,比如说12小时的小步舞曲,这是当天的总时间,比如说1-4,不是1-2-3-4,因为2-3之间的时间不应该被计算,我怎么能解决这个问题呢?所以你说的是,打孔2和3之间的时间不应该被加总,5和6之间的时间等等…我想我明白了…leme给你一些其他的东西啊,准确地说,想象一下如果你刷卡说你的在,那是1,然后你再刷卡,所以你的离开,比如晚餐,2,然后3会回来,然后4会在一天结束时离开好吧,我更新了查询…现在应该对你有用了。我基本上是从连接的左侧移除双关语,所以它们只会在连接的右侧被考虑。这意味着奇数是双关语…偶数是双关语…在偶数也被认为是双关语之前。