簡體   English   中英

如何在MSSQL上執行此查詢

[英]How to do this Query on MSSQL

我需要進行查詢以顯示每天的入口(TerminalID = 1)和出口(其中TerminalID = 2),但是如果UserID僅在這一天有出口標記,請在入口值上使用08:00:00,然后如果沒有出口標記,則在同一天用20:00:00設置出口值,我需要知道IDUser在這里有多少天,每天有多少時間,這就是我的表格:

SQLFiddle

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

SQL小提琴

嘗試這樣的事情。 請注意,我尚未運行查詢,因此其中可能存在一個簡單的語法錯誤(主要是在轉換中-真的不確定),如果有問題,請在評論中告知我。

;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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM