SQL Server条件查询

时间:2015-08-23 06:48:17

标签: sql-server sql-server-2005

我有一张参加考勤表的表格如下:

enter image description here

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

enter image description here

使用英国/法国格式(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

基本上我需要一个查询来使用上面的导出格式选择每天的最短时间(签到)和最长时间(签出),但是当没有值办理登记入住和退房时,然后查询应该返回(null)时间。

1 个答案:

答案 0 :(得分:1)

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

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 server(2005,2000),您可以使用convertchar(10)隔离date列的datetime部分:

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.