select门禁进出时间table
select first in and last out time from door access table
这是我的门禁 table, [dbo].[tblAccess]
+------------+--------------+----------+-----------------+------------+
| EmployeeId | EmployeeName | Location | AccessTime | ReaderType |
+------------+--------------+----------+-----------------+------------+
| _1346 | A | L1 | 7/11/2014 10:00 | IN |
| _1347 | B | L2 | 7/10/2014 10:58 | IN |
| _1346 | A | L3 | 7/11/2014 23:39 | OUT |
| _1347 | B | L4 | 7/10/2014 23:58 | OUT |
| _1364 | C | L5 | 7/11/2014 10:00 | IN |
| _1367 | D | L6 | 7/10/2014 10:58 | IN |
| _1367 | D | L7 | 7/10/2014 22:42 | OUT |
| _1364 | C | L8 | 7/11/2014 23:58 | OUT |
| _1422 | E | L9 | 7/11/2014 23:58 | IN |
| _1422 | E | L10 | 7/11/2014 23:10 | IN |
| _1111 | F | L20 | 7/10/2014 23:10 | OUT |
+------------+--------------+----------+-----------------+------------+
条件
- 假设员工将在同一天进出。
- 同一天会有多次进出,因为employees.So需要先进后出。
- 需要按天获取详细信息,在两个日期之间,按 EmployeeId 分组
- (InTime, InLocation) 或 (OUTTime, OutLocation) 对于员工可以为 null
- 如果 (InTime) 为空,则 FirstInLocation 和持续时间将为空,OutTime 也相同(如结果 1 所示)。 [如果很难,那么就不要显示IN时间或OUT时间为空的那一天的详细信息(显示在结果2中)]
- 持续时间 = (FirstInTime - LastOutTime)
需要结果
我想selectEmployeeId、EmployeeName、Date、FirstInTime、FirstInLocation、LastOutTime、LastOutLocation、持续时间。
结果 1
+-------+---------+-----------+-------+--------+--------+---------+---------+
| EmpID | EmpName | Date | InLoc | InTime | OutLoc | OutTime | Dur(Hr) |
+-------+---------+-----------+-------+--------+--------+---------+---------+
| _1346 | A | 7/11/2014 | L1 | 10:00 | L3 | 23:39 | 13:39 |
| _1347 | B | 7/10/2014 | L2 | 10:58 | L4 | 23:58 | 13:02 |
| _1364 | C | 7/11/2014 | L5 | 10:00 | L8 | 23:58 | 13:58 |
| _1367 | D | 7/10/2014 | L6 | 10:58 | L7 | 22:42 | 11:44 |
| _1422 | E | 7/10/2014 | L10 | 23:10 | | | |
| _1111 | F | 7/10/2014 | | | L20 | 23:10 | |
+-------+---------+-----------+-------+--------+--------+---------+---------+
或
只需跳过空的 IN 或 OUT 行。像这样的东西。
结果 2
+-------+---------+-----------+-------+--------+--------+---------+---------+
| EmpID | EmpName | Date | InLoc | InTime | OutLoc | OutTime | Dur(Hr) |
+-------+---------+-----------+-------+--------+--------+---------+---------+
| _1346 | A | 7/11/2014 | L1 | 10:00 | L3 | 23:39 | 13:39 |
| _1347 | B | 7/10/2014 | L2 | 10:58 | L4 | 23:58 | 13:02 |
| _1364 | C | 7/11/2014 | L5 | 10:00 | L8 | 23:58 | 13:58 |
| _1367 | D | 7/10/2014 | L6 | 10:58 | L7 | 22:42 | 11:44 |
+-------+---------+-----------+-------+--------+--------+---------+---------+
到目前为止,我已经使用以下链接进行了一些查询。但它的解决方案不完整,而且我是 CTE 的新手,所以我无法编辑链接中给出的任何查询。
- How to get first login and last logout time from sql server?
- SQL Query for time In/Out attendance
- http://database.ittoolbox.com/groups/technical-functional/sql-l/query-to-pair-user-biometric-attendance-record-in-first-in-last-out-format-5132155
我有这个问题。
;with cte as
(select *, rank() over(partition by EmployeeId order by [AccessTime]) rn
from tblAccess)
select src.EmployeeId, src.EmployeeName, convert(date, src.[AccessTime]) as [AccessTime],
concat(datepart(hour,src.[AccessTime]),':',datepart(minute,src.[AccessTime])) as [TimeIn],
concat(datepart(hour,tgt.[AccessTime]),':',datepart(minute,tgt.[AccessTime])) as [TimeOut],
concat(datediff(minute,src.[AccessTime],tgt.[AccessTime])/60,':',datediff(minute,src.[AccessTime],tgt. [AccessTime])%60) as [Hours]
from cte src
inner join cte tgt on src.EmployeeId = tgt.EmployeeId and src.rn + 1 = tgt.rn and src.rn % 2 = 1
它return 结果有些不错,但不满足所有条件。我不知道如何编辑 CTE,因为我是新手。有什么办法吗?
试试这个:
示例数据
CREATE TABLE tblAccess(
EmployeeID VARCHAR(20),
EmployeeName VARCHAR(20),
Location VARCHAR(20),
AccessTime DATETIME,
ReaderType VARCHAR(3)
)
INSERT INTO tblAccess VALUES
('_1346', 'A', 'L1', '7/11/2014 10:00', 'IN'),
('_1347', 'B', 'L2', '7/10/2014 10:58', 'IN'),
('_1346', 'A', 'L3', '7/11/2014 23:39', 'OUT'),
('_1347', 'B', 'L4', '7/10/2014 23:58', 'OUT'),
('_1364', 'C', 'L5', '7/11/2014 10:00', 'IN'),
('_1367', 'D', 'L6', '7/10/2014 10:58', 'IN'),
('_1367', 'D', 'L7', '7/10/2014 22:42', 'OUT'),
('_1364', 'C', 'L8', '7/11/2014 23:58', 'OUT'),
('_1422', 'E', 'L9', '7/11/2014 23:58', 'IN'),
('_1422', 'E', 'L10', '7/11/2014 23:10', 'IN'),
('_1111', 'F', 'L20', '7/10/2014 23:10', 'OUT');
解决方案
;WITH CTE AS(
SELECT
EmployeeID,
EmployeeName,
AccessDate = CAST(AccessTime AS DATE),
AccessTime = CAST(AccessTime AS TIME),
Location,
ReaderType,
In_RN = ROW_NUMBER() OVER(PARTITION BY EmployeeId, CAST(AccessTime AS DATE), ReaderType ORDER BY CAST(AccessTime AS TIME) ASC),
Out_RN = ROW_NUMBER() OVER(PARTITION BY EmployeeId, CAST(AccessTime AS DATE), ReaderType ORDER BY CAST(AccessTime AS TIME) DESC)
FROM tblAccess
)
SELECT
EmployeeID,
EmployeeName,
[Date] = CONVERT(VARCHAR(10), AccessDate, 101),
InLoc = ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN Location END), ''),
InTime= ISNULL(SUBSTRING(CONVERT(VARCHAR(20), MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END)), 1, 5), ''),
OutLoc = ISNULL(MAX(CASE WHEN ReaderType = 'OUT' AND OUT_RN = 1 THEN Location END), ''),
OutTime = ISNULL(SUBSTRING(CONVERT(VARCHAR(20), MAX(CASE WHEN ReaderType = 'OUT' AND OUT_RN = 1 THEN AccessTime END)), 1, 5), ''),
Duration = ISNULL(RIGHT('00' +
CONVERT(VARCHAR(2), DATEDIFF(MINUTE,
MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END),
MAX(CASE WHEN ReaderType = 'OUT' AND OUT_RN = 1 THEN AccessTime END)
)/60), 2) + ':' +
RIGHT('00' +CONVERT(VARCHAR(2), DATEDIFF(MINUTE,
MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END),
MAX(CASE WHEN ReaderType = 'OUT' AND OUT_RN = 1 THEN AccessTime END)
)%60), 2)
,'')
FROM CTE
GROUP BY EmployeeID, EmployeeName, AccessDate
ORDER BY EmployeeName, AccessDate
结果
EmployeeID EmployeeName Date InLoc InTime OutLoc OutTime Duration
-------------------- ------------ ---------- -------- ------ ------- ------- --------
_1346 A 07/11/2014 L1 10:00 L3 23:39 13:39
_1347 B 07/10/2014 L2 10:58 L4 23:58 13:00
_1364 C 07/11/2014 L5 10:00 L8 23:58 13:58
_1367 D 07/10/2014 L6 10:58 L7 22:42 11:44
_1422 E 07/11/2014 L10 23:10
_1111 F 07/10/2014 L20 23:10
这是我的门禁 table, [dbo].[tblAccess]
+------------+--------------+----------+-----------------+------------+
| EmployeeId | EmployeeName | Location | AccessTime | ReaderType |
+------------+--------------+----------+-----------------+------------+
| _1346 | A | L1 | 7/11/2014 10:00 | IN |
| _1347 | B | L2 | 7/10/2014 10:58 | IN |
| _1346 | A | L3 | 7/11/2014 23:39 | OUT |
| _1347 | B | L4 | 7/10/2014 23:58 | OUT |
| _1364 | C | L5 | 7/11/2014 10:00 | IN |
| _1367 | D | L6 | 7/10/2014 10:58 | IN |
| _1367 | D | L7 | 7/10/2014 22:42 | OUT |
| _1364 | C | L8 | 7/11/2014 23:58 | OUT |
| _1422 | E | L9 | 7/11/2014 23:58 | IN |
| _1422 | E | L10 | 7/11/2014 23:10 | IN |
| _1111 | F | L20 | 7/10/2014 23:10 | OUT |
+------------+--------------+----------+-----------------+------------+
条件
- 假设员工将在同一天进出。
- 同一天会有多次进出,因为employees.So需要先进后出。
- 需要按天获取详细信息,在两个日期之间,按 EmployeeId 分组
- (InTime, InLocation) 或 (OUTTime, OutLocation) 对于员工可以为 null
- 如果 (InTime) 为空,则 FirstInLocation 和持续时间将为空,OutTime 也相同(如结果 1 所示)。 [如果很难,那么就不要显示IN时间或OUT时间为空的那一天的详细信息(显示在结果2中)]
- 持续时间 = (FirstInTime - LastOutTime)
需要结果
我想selectEmployeeId、EmployeeName、Date、FirstInTime、FirstInLocation、LastOutTime、LastOutLocation、持续时间。
结果 1
+-------+---------+-----------+-------+--------+--------+---------+---------+
| EmpID | EmpName | Date | InLoc | InTime | OutLoc | OutTime | Dur(Hr) |
+-------+---------+-----------+-------+--------+--------+---------+---------+
| _1346 | A | 7/11/2014 | L1 | 10:00 | L3 | 23:39 | 13:39 |
| _1347 | B | 7/10/2014 | L2 | 10:58 | L4 | 23:58 | 13:02 |
| _1364 | C | 7/11/2014 | L5 | 10:00 | L8 | 23:58 | 13:58 |
| _1367 | D | 7/10/2014 | L6 | 10:58 | L7 | 22:42 | 11:44 |
| _1422 | E | 7/10/2014 | L10 | 23:10 | | | |
| _1111 | F | 7/10/2014 | | | L20 | 23:10 | |
+-------+---------+-----------+-------+--------+--------+---------+---------+
或
只需跳过空的 IN 或 OUT 行。像这样的东西。
结果 2
+-------+---------+-----------+-------+--------+--------+---------+---------+
| EmpID | EmpName | Date | InLoc | InTime | OutLoc | OutTime | Dur(Hr) |
+-------+---------+-----------+-------+--------+--------+---------+---------+
| _1346 | A | 7/11/2014 | L1 | 10:00 | L3 | 23:39 | 13:39 |
| _1347 | B | 7/10/2014 | L2 | 10:58 | L4 | 23:58 | 13:02 |
| _1364 | C | 7/11/2014 | L5 | 10:00 | L8 | 23:58 | 13:58 |
| _1367 | D | 7/10/2014 | L6 | 10:58 | L7 | 22:42 | 11:44 |
+-------+---------+-----------+-------+--------+--------+---------+---------+
到目前为止,我已经使用以下链接进行了一些查询。但它的解决方案不完整,而且我是 CTE 的新手,所以我无法编辑链接中给出的任何查询。
- How to get first login and last logout time from sql server?
- SQL Query for time In/Out attendance
- http://database.ittoolbox.com/groups/technical-functional/sql-l/query-to-pair-user-biometric-attendance-record-in-first-in-last-out-format-5132155
我有这个问题。
;with cte as
(select *, rank() over(partition by EmployeeId order by [AccessTime]) rn
from tblAccess)
select src.EmployeeId, src.EmployeeName, convert(date, src.[AccessTime]) as [AccessTime],
concat(datepart(hour,src.[AccessTime]),':',datepart(minute,src.[AccessTime])) as [TimeIn],
concat(datepart(hour,tgt.[AccessTime]),':',datepart(minute,tgt.[AccessTime])) as [TimeOut],
concat(datediff(minute,src.[AccessTime],tgt.[AccessTime])/60,':',datediff(minute,src.[AccessTime],tgt. [AccessTime])%60) as [Hours]
from cte src
inner join cte tgt on src.EmployeeId = tgt.EmployeeId and src.rn + 1 = tgt.rn and src.rn % 2 = 1
它return 结果有些不错,但不满足所有条件。我不知道如何编辑 CTE,因为我是新手。有什么办法吗?
试试这个:
示例数据
CREATE TABLE tblAccess(
EmployeeID VARCHAR(20),
EmployeeName VARCHAR(20),
Location VARCHAR(20),
AccessTime DATETIME,
ReaderType VARCHAR(3)
)
INSERT INTO tblAccess VALUES
('_1346', 'A', 'L1', '7/11/2014 10:00', 'IN'),
('_1347', 'B', 'L2', '7/10/2014 10:58', 'IN'),
('_1346', 'A', 'L3', '7/11/2014 23:39', 'OUT'),
('_1347', 'B', 'L4', '7/10/2014 23:58', 'OUT'),
('_1364', 'C', 'L5', '7/11/2014 10:00', 'IN'),
('_1367', 'D', 'L6', '7/10/2014 10:58', 'IN'),
('_1367', 'D', 'L7', '7/10/2014 22:42', 'OUT'),
('_1364', 'C', 'L8', '7/11/2014 23:58', 'OUT'),
('_1422', 'E', 'L9', '7/11/2014 23:58', 'IN'),
('_1422', 'E', 'L10', '7/11/2014 23:10', 'IN'),
('_1111', 'F', 'L20', '7/10/2014 23:10', 'OUT');
解决方案
;WITH CTE AS(
SELECT
EmployeeID,
EmployeeName,
AccessDate = CAST(AccessTime AS DATE),
AccessTime = CAST(AccessTime AS TIME),
Location,
ReaderType,
In_RN = ROW_NUMBER() OVER(PARTITION BY EmployeeId, CAST(AccessTime AS DATE), ReaderType ORDER BY CAST(AccessTime AS TIME) ASC),
Out_RN = ROW_NUMBER() OVER(PARTITION BY EmployeeId, CAST(AccessTime AS DATE), ReaderType ORDER BY CAST(AccessTime AS TIME) DESC)
FROM tblAccess
)
SELECT
EmployeeID,
EmployeeName,
[Date] = CONVERT(VARCHAR(10), AccessDate, 101),
InLoc = ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN Location END), ''),
InTime= ISNULL(SUBSTRING(CONVERT(VARCHAR(20), MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END)), 1, 5), ''),
OutLoc = ISNULL(MAX(CASE WHEN ReaderType = 'OUT' AND OUT_RN = 1 THEN Location END), ''),
OutTime = ISNULL(SUBSTRING(CONVERT(VARCHAR(20), MAX(CASE WHEN ReaderType = 'OUT' AND OUT_RN = 1 THEN AccessTime END)), 1, 5), ''),
Duration = ISNULL(RIGHT('00' +
CONVERT(VARCHAR(2), DATEDIFF(MINUTE,
MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END),
MAX(CASE WHEN ReaderType = 'OUT' AND OUT_RN = 1 THEN AccessTime END)
)/60), 2) + ':' +
RIGHT('00' +CONVERT(VARCHAR(2), DATEDIFF(MINUTE,
MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END),
MAX(CASE WHEN ReaderType = 'OUT' AND OUT_RN = 1 THEN AccessTime END)
)%60), 2)
,'')
FROM CTE
GROUP BY EmployeeID, EmployeeName, AccessDate
ORDER BY EmployeeName, AccessDate
结果
EmployeeID EmployeeName Date InLoc InTime OutLoc OutTime Duration
-------------------- ------------ ---------- -------- ------ ------- ------- --------
_1346 A 07/11/2014 L1 10:00 L3 23:39 13:39
_1347 B 07/10/2014 L2 10:58 L4 23:58 13:00
_1364 C 07/11/2014 L5 10:00 L8 23:58 13:58
_1367 D 07/10/2014 L6 10:58 L7 22:42 11:44
_1422 E 07/11/2014 L10 23:10
_1111 F 07/10/2014 L20 23:10