[英]How to do this Query on MSSQL
我需要進行查詢以顯示每天的入口(TerminalID = 1)和出口(其中TerminalID = 2),但是如果UserID僅在這一天有出口標記,請在入口值上使用08:00:00,然后如果沒有出口標記,則在同一天用20:00:00設置出口值,我需要知道IDUser在這里有多少天,每天有多少時間,這就是我的表格:
ID TransactionTime TerminalID UserID
1 2014-04-01 08:59 1 1
2 2014-04-01 09:09 1 1
3 2014-04-01 09:59 2 1
4 2014-04-01 10:59 1 1
5 2014-04-01 18:59 2 1
6 2014-05-01 08:59 1 1
7 2014-04-01 09:59 1 2
8 2014-04-01 18:59 2 2
9 2014-05-01 08:59 2 2
我需要的結果是:
UserID MarkEntrance MarkExit TimeHere
1 2014-04-01 08:59 2014-04-01 09:59 01:00:00
1 2014-04-01 10:59 2014-04-01 18:59 08:00:00
1 2014-05-01 08:59 2014-05-01 20:00 11:01:00
我可以這樣做:
SELECT TOP 1000
pna.UserID
,Convert(char(10),pna.TransactionTime, 103) as DateOfMark
,MarkEntrance =
CASE WHEN
(SELECT MIN(TransactionTime) FROM [NGAC_AUTHLOG] as na WHERE na.TerminalID = 1 AND Convert(char(10),na.TransactionTime, 103) = Convert(char(10),pna.TransactionTime, 103) AND na.UserID = pna.UserID ) IS NOT NULL
THEN
(SELECT MIN(TransactionTime) FROM [NGAC_AUTHLOG] as na WHERE na.TerminalID = 1 AND Convert(char(10),na.TransactionTime, 103) = Convert(char(10),pna.TransactionTime, 103) AND na.UserID = pna.UserID )
ELSE convert(datetime,Convert(char(10),pna.TransactionTime, 103) + ' 08:00:00')
END
,MarkExit =
CASE WHEN
(SELECT MAX(TransactionTime) FROM [NGAC_AUTHLOG] as na WHERE na.TerminalID = 2 AND Convert(char(10),na.TransactionTime, 103) = Convert(char(10),pna.TransactionTime, 103) AND na.UserID = pna.UserID ) IS NOT NULL
THEN
(SELECT MAX(TransactionTime) FROM [NGAC_AUTHLOG] as na WHERE na.TerminalID = 2 AND Convert(char(10),na.TransactionTime, 103) = Convert(char(10),pna.TransactionTime, 103) AND na.UserID = pna.UserID )
ELSE convert(datetime,Convert(char(10),pna.TransactionTime, 103) + ' 20:00:00')
END
,TimeHere =
Convert(char(8),
CASE WHEN
(SELECT MAX(TransactionTime) FROM [NGAC_AUTHLOG] as na WHERE na.TerminalID = 2 AND Convert(char(10),na.TransactionTime, 103) = Convert(char(10),pna.TransactionTime, 103) AND na.UserID = pna.UserID ) IS NOT NULL
THEN
(SELECT MAX(TransactionTime) FROM [NGAC_AUTHLOG] as na WHERE na.TerminalID = 2 AND Convert(char(10),na.TransactionTime, 103) = Convert(char(10),pna.TransactionTime, 103) AND na.UserID = pna.UserID )
ELSE convert(datetime,Convert(char(10),pna.TransactionTime, 103) + ' 20:00:00')
END -
CASE WHEN
(SELECT MIN(TransactionTime) FROM [NGAC_AUTHLOG] as na WHERE na.TerminalID = 1 AND Convert(char(10),na.TransactionTime, 103) = Convert(char(10),pna.TransactionTime, 103) AND na.UserID = pna.UserID ) IS NOT NULL
THEN
(SELECT MIN(TransactionTime) FROM [NGAC_AUTHLOG] as na WHERE na.TerminalID = 1 AND Convert(char(10),na.TransactionTime, 103) = Convert(char(10),pna.TransactionTime, 103) AND na.UserID = pna.UserID )
ELSE convert(datetime,Convert(char(10),pna.TransactionTime, 103) + ' 08:00:00')
END
, 14)
FROM NGAC_AUTHLOG as pna
GROUP BY pna.UserID, Convert(char(10),pna.TransactionTime, 103)
但是在我的查詢中,我只是通過UserID知道第一個入口和最后一個出口,但是他每天可以有很多標記。
(我使用了MIN和MAX,但這種方式僅顯示了一個大標記,將當天的所有標記合並)
嘗試這樣的事情。 第一個並集部分將匹配“入口到出口”和“孤兒入口”的所有記錄。 聯合的第二部分負責處理孤立的退出記錄。
解決方案1:
SELECT *, Convert(char(8), MarkExit - MarkEntrance, 14) TimeHere
FROM
(
SELECT
A.UserID, A.TransactionTime MarkEntrance, ISNULL(ExitTime, DateAdd(hh, 20, CONVERT(VARCHAR(10), A.TransactionTime, 101))) MarkExit
FROM NGAC_AUTHLOG A
OUTER APPLY
(
SELECT MIN(TransactionTime) ExitTime
FROM NGAC_AUTHLOG B
WHERE B.TerminalID = 2
AND B.UserID = A.UserID
AND B.TransactionTime > A.TransactionTime
) B
WHERE A.TerminalID = 1
UNION ALL
--This looks for orphan Exit Record
SELECT A.UserID, DateAdd(hh, 8, CONVERT(VARCHAR(10), max(A.TransactionTime), 101)), max(A.TransactionTime)
FROM NGAC_AUTHLOG A
WHERE A.TerminalID = 2
AND EXISTS
(SELECT 1
FROM
(SELECT UserID, CONVERT(VARCHAR(10), TransactionTime, 101) T2Date, COUNT(*) T2Count
FROM NGAC_AUTHLOG
WHERE TerminalID = 2
GROUP BY UserID, CONVERT(VARCHAR(10), TransactionTime, 101)) X
LEFT JOIN
(SELECT UserID, CONVERT(VARCHAR(10), TransactionTime, 101) T1Date, COUNT(*) T1Count
FROM NGAC_AUTHLOG
WHERE TerminalID = 1
GROUP BY UserID, CONVERT(VARCHAR(10), TransactionTime, 101)) Y
ON X.UserID = Y.UserID
AND X.T2Date = Y.T1Date
WHERE X.T2Count > ISNULL(Y.T1Count,0)
AND X.UserID = A.UserID
AND X.T2Date = CONVERT(VARCHAR(10), TransactionTime, 101)
)
GROUP BY A.UserID, CONVERT(VARCHAR(10), TransactionTime, 101)
) X
解決方案2:假設是否有孤立的退出記錄,則該用戶當天只有1條退出記錄
SELECT *, Convert(char(8), MarkExit - MarkEntrance, 14) TimeHere
FROM
(
SELECT
A.UserID, A.TransactionTime MarkEntrance, ISNULL(ExitTime, DateAdd(hh, 20, CONVERT(VARCHAR(10), A.TransactionTime, 101))) MarkExit
FROM NGAC_AUTHLOG A
OUTER APPLY
(
SELECT MIN(TransactionTime) ExitTime
FROM NGAC_AUTHLOG B
WHERE B.TerminalID = 2
AND B.UserID = A.UserID
AND B.TransactionTime > A.TransactionTime
) B
WHERE A.TerminalID = 1
UNION ALL
--This looks for orphan Exit Record
SELECT A.UserID, DateAdd(hh, 8, CONVERT(VARCHAR(10), A.TransactionTime, 101)), A.TransactionTime
FROM NGAC_AUTHLOG A
WHERE A.TerminalID = 2
AND NOT EXISTS
(SELECT 1
FROM NGAC_AUTHLOG B
WHERE B.TerminalID = 1
AND A.UserID = B.UserID
AND CONVERT(VARCHAR(10), A.TransactionTime, 101) = CONVERT(VARCHAR(10), B.TransactionTime, 101))
) X
嘗試這樣的事情。 請注意,我尚未運行查詢,因此其中可能存在一個簡單的語法錯誤(主要是在轉換中-真的不確定),如果有問題,請在評論中告知我。
;WITH minEntranceInDay as(
SELECT MIN(transactionTime) EntranceTime,Convert(DateTime( Convert(char(10),na.TransactionTime)), 103) Day, UserId
FROM NGAC_AUTHLOG WHERE TerminalId = 1
GROUP BY Convert(DateTime( Convert(char(10),na.TransactionTime)), 103), UserId
), maxExitInDay as(
SELECT MAX(transactionTime) ExitTime, Convert(DateTime( Convert(char(10),na.TransactionTime)) Day, UserId
FROM NGAC_AUTHLOG WHERE TerminalId = 2
GROUP BY Convert(DateTime( Convert(char(10),na.TransactionTime)), 103), UserId
), usersAndDates as(
SELECT DISTINCT Convert(DateTime( Convert(char(10),na.TransactionTime)) Day, UserId
FROM NGAC_AUTHLOG
), GroupedData As (
SELECT ud.UserId, COALESCE(me.minEntranceInDay,Dateadd(h,8,ud.Day)) EntranceTime, COALESCE(mx.maxExitInDay,Dateadd(h,20,ud.Day)) ExitDate
FROM usersAndDates ud
LEFT JOIN minEntranceInDay me ON me.UserId = ud.UserId AND me.Day = ud.Day
LEFT JOIN maxExitInDay mx ON mx.UserId = ud.UserId AND mx.Day = ud.Day
)
SELECT *, DATEDIFF(h,EntranceTime,ExitTime)+":"+DATEDIFF(m,EntranceTime,ExitTime)+":"+DATEDIFF(s,EntranceTime,ExitTime) TimeHere
FROM GroupedData
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.