处理SQL Datetime中缺少登录/注销值
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了处理SQL Datetime中缺少登录/注销值相关的知识,希望对你有一定的参考价值。
我的Sql查询:
CREATE TABLE TimeLog (
[User] NVARCHAR(6),
[Event] NVARCHAR(3),
[Time] DATETIME
);
INSERT INTO TimeLog VALUES
(N'Jibran',N'IN','2015-04-15 00:31:00'),
(N'Jibran',N'IN','2015-04-16 20:10:00'),
(N'Jibran',N'IN','2015-04-21 14:59:00'),
(N'Jibran',N'OUT','2015-04-22 01:01:00'),
(N'Jibran',N'IN','2015-04-22 10:46:00'),
(N'Jibran',N'OUT','2015-04-23 00:58:00'),
(N'Jibran',N'IN','2015-04-23 14:50:00'),
(N'Jibran',N'OUT','2015-04-24 01:37:00'),
(N'Jibran',N'OUT','2015-04-25 01:01:00'),
(N'Jibran',N'OUT','2015-04-27 00:57:00'),
(N'Jibran',N'IN','2015-04-17 10:32:00'),
(N'Jibran',N'IN','2015-04-29 15:03:00'),
(N'Jibran',N'OUT','2015-05-01 00:44:00'),
(N'Jibran',N'OUT','2015-05-02 01:19:00'),
(N'Jibran',N'IN','2015-05-02 15:08:00'),
(N'Jibran',N'OUT','2015-05-03 01:08:00'),
(N'Jibran',N'IN','2015-05-03 15:06:00'),
(N'Jibran',N'OUT','2015-05-04 01:01:00'),
(N'Jibran',N'IN','2015-05-04 15:11:00'),
(N'Jibran',N'OUT','2015-05-05 01:08:00');
SELECT TOP (30) UserName, EventName, EventTime
From AttendanceEvents
Where UserName = 'Jibran'
结果是 :
有没有办法处理没有OUT日期时间值的每个IN值的缺失值?
但无法理解它的一半。
如何获取日期时间平均值以将其用于缺失值?
期望输出将具有每个IN的OUT值。
谢谢。
答案
我想出了一个解决方案,将缺少的行添加到表中 - 两者都缺少in
行和缺少out
行。
我所做的一件事与你提出的不同的是,缺少的行在他们的源行中完成了8小时的一天。
请注意,每次只能与单个用户一起使用。
所以这是如何:
首先,我创建了一个公用表表达式,其中包含表中属于特定用户的所有行。在那个cte我用lag
和lead
来获取下一个事件,前一个事件和下一个事件时间,以及一个row_number列。
然后我使用了一个基于cte的三个查询的联合 - 一个用于原始行,一个用于具有in
事件的新行,一个用于具有out
事件的新行。
该脚本基于您的示例数据,您可以看到online demo on rextester.
DECLARE @User nvarchar(6) = N'Jibran';
WITH CTE AS
(
SELECT [User],
[Event],
[Time],
ROW_NUMBER() OVER(ORDER BY [Time]) + 0.0 As rn,
LAG([Event]) OVER(ORDER BY [Time]) As PrevEvent,
LEAD([Event]) OVER(ORDER BY [Time]) As NextEvent,
LEAD([Time]) OVER(ORDER BY [Time]) As NextEventTime
FROM TimeLog
WHERE [User] = @User
)
SELECT [User],
'OUT' As [Event],
DATEADD(HOUR, 8, [Time]) As [Time],
rn + 0.5 As rn
FROM CTE
WHERE NextEvent = [Event]
AND [Event] = 'IN'
UNION ALL
SELECT [User],
'IN' As [Event],
DATEADD(HOUR, -8, [NextEventTime]) As [Time],
rn - 0.3 As rn
FROM CTE
WHERE PrevEvent = [Event]
AND [Event] = 'OUT'
UNION ALL
SELECT [User],
[Event],
[Time],
rn
FROM CTE
ORDER BY rn
结果:
User Event Time rn
Jibran IN 15.04.2015 00:31:00 1,0
Jibran OUT 15.04.2015 08:31:00 1,5
Jibran IN 16.04.2015 20:10:00 2,0
Jibran OUT 17.04.2015 04:10:00 2,5
Jibran IN 17.04.2015 10:32:00 3,0
Jibran OUT 17.04.2015 18:32:00 3,5
Jibran IN 21.04.2015 14:59:00 4,0
Jibran OUT 22.04.2015 01:01:00 5,0
Jibran IN 22.04.2015 10:46:00 6,0
Jibran OUT 23.04.2015 00:58:00 7,0
Jibran IN 23.04.2015 14:50:00 8,0
Jibran OUT 24.04.2015 01:37:00 9,0
Jibran IN 26.04.2015 16:57:00 9,7
Jibran OUT 25.04.2015 01:01:00 10,0
Jibran IN 29.04.2015 07:03:00 10,7
Jibran OUT 27.04.2015 00:57:00 11,0
Jibran IN 29.04.2015 15:03:00 12,0
Jibran OUT 01.05.2015 00:44:00 13,0
Jibran IN 02.05.2015 07:08:00 13,7
Jibran OUT 02.05.2015 01:19:00 14,0
Jibran IN 02.05.2015 15:08:00 15,0
Jibran OUT 03.05.2015 01:08:00 16,0
Jibran IN 03.05.2015 15:06:00 17,0
Jibran OUT 04.05.2015 01:01:00 18,0
Jibran IN 04.05.2015 15:11:00 19,0
Jibran OUT 05.05.2015 01:08:00 20,0
旁注:您可以通过rn告诉哪一行添加了哪一部分联合所有查询。
更新
在我们在问题的评论中进行对话之后 - 为了获得不同列中的详细信息,我将联合所有查询包装在另一个cte中,并在其上加上一个cte来获取bigint行号。然后,这只是一个带有扭曲的条件聚合问题 - 使用交叉应用将偶数和奇数行数组合成组。
这是完整的脚本 - 当然,an online demo:
DECLARE @User nvarchar(6) = N'Jibran';
WITH CTE AS
(
SELECT [User],
[Event],
[Time],
ROW_NUMBER() OVER(ORDER BY [Time]) + 0.0 As rn,
LAG([Event]) OVER(ORDER BY [Time]) As PrevEvent,
LEAD([Event]) OVER(ORDER BY [Time]) As NextEvent,
LEAD([Time]) OVER(ORDER BY [Time]) As NextEventTime
FROM TimeLog
WHERE [User] = @User
), CTERows AS
(
-- Added out rows
SELECT [User],
'OUT' As [Event],
DATEADD(HOUR, 8, [Time]) As [Time],
rn + 0.5 As rn
FROM CTE
WHERE NextEvent = [Event]
AND [Event] = 'IN'
UNION ALL
-- Added in rows
SELECT [User],
'IN' As [Event],
DATEADD(HOUR, -8, [NextEventTime]) As [Time],
rn - 0.3 As rn
FROM CTE
WHERE PrevEvent = [Event]
AND [Event] = 'OUT'
UNION ALL
-- Existing rows
SELECT [User],
[Event],
[Time],
rn
FROM CTE
), CTEIntNumberedRows AS
(
SELECT [User],
[Event],
[Time],
ROW_NUMBER() OVER (ORDER BY rn) As rn
FROM CteRows
)
SELECT [User],
MAX(CASE WHEN [Event] = 'IN' THEN [Time] END) As 'IN',
MAX(CASE WHEN [Event] = 'OUT' THEN [Time] END) As 'OUT',
Pairs
FROM CTEIntNumberedRows
CROSS APPLY
(
SELECT CASE WHEN rn % 2 = 0 THEN rn-1 ELSE rn END As Pairs
) x
GROUP BY [User], Pairs
ORDER BY Pairs
以上是关于处理SQL Datetime中缺少登录/注销值的主要内容,如果未能解决你的问题,请参考以下文章