SQL 服务器条件查询

SQL Server conditional query

我有一个 table 出勤条目,如下所示:

我需要查询以导出以下格式:

使用 British/French 格式 (103)

显示入住和退房时间

我尝试了以下查询:

SELECT 
    UserID, 
    (SELECT MIN(checktime) 
     FROM [FingerPrint].[dbo].[CHECKINOUT] I 
     WHERE CONVERT(VARCHAR(10), i.checktime, 111) = CONVERT(VARCHAR(10), p.checktime, 111)  
       AND i.userid = p.userid),   
   (SELECT MAX(checktime) 
    FROM [FingerPrint].[dbo].[CHECKINOUT] I 
    WHERE CONVERT(VARCHAR(10), i.checktime, 111) = CONVERT(VARCHAR(10), p.checktime, 111) 
      AND i.userid = p.userid)
FROM 
    [FingerPrint].[dbo].[CHECKINOUT] p
GROUP BY 
    p.checktime, p.UserID

基本上我需要使用上面的导出格式查询 select 每天的最短时间(签到)和最长时间(签出),但是当没有签到值时-入住和退房,然后查询应该 return (null) for time.

所以基本上你从这样的事情开始:

SELECT  UserId, 
        CAST(CheckTime As Date) As CheckDate, 
        MIN(CheckTime) As CheckIn, 
        MAX(CheckTime) As CheckOut
FROM [FingerPrint].[dbo].[CHECKINOUT]
GROUP BY UserId, CAST(CheckTime As Date)

对于旧版本的sql服务器(2005、2000),你可以使用convertchar(10)来隔离[=16=的date部分] 专栏:

SELECT  UserId, 
        CONVERT(char(10), CheckTime, 102) As CheckDate, /*Convert datetime format to Date*/
        MIN(CheckTime) As CheckIn, 
        MAX(CheckTime) As CheckOut
FROM [FingerPrint].[dbo].[CHECKINOUT]
GROUP BY UserId, CONVERT(char(10), CheckTime, 102)

see fiddle here

然后你需要弄清楚如果用户一天只有一条记录,你想显示什么。

此外,当用户在一个日期签到并在另一天签出时,夜班会发生什么情况?

更好的解决方案是添加一个位列来指定记录是用于签入还是签出。

更新

使用 case 您可以检查当前时间是在您要设置为签入和签出之间的分隔符的一天中的任何时间之前还是之后。在这个例子中,我使用了中午 12 点。

SELECT  UserId, 
        CONVERT(char(10), CheckTime, 102) As CheckDate, /*Convert datetime format to Date*/
        CASE WHEN MIN(CheckTime) <> MAX(CheckTime) THEN
          MIN(CheckTime) 
        ELSE
          CASE WHEN MIN(CheckTime) < DATEADD(Hour, 12, CONVERT(Datetime, CONVERT(char(10), CheckTime, 102), 102)) THEN 
            NULL
          ELSE
            MIN(CheckTime)
          END
        END As CheckIn, 
        CASE WHEN MIN(CheckTime) <> MAX(CheckTime) THEN
          MAX(CheckTime) 
        ELSE
          CASE WHEN MAX(CheckTime) > DATEADD(Hour, 12, CONVERT(Datetime, CONVERT(char(10), CheckTime, 102), 102)) THEN 
            NULL
          ELSE
            MAX(CheckTime)
          END
        END As CheckOut
FROM [CHECKINOUT]
GROUP BY UserId, CONVERT(char(10), CheckTime, 102)

Here is the relevant fiddle.