我有一张参加考勤表的表格如下:
我需要一个查询来导出以下格式:
使用英国/法国格式(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)时间。
答案 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),您可以使用convert
与char(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)
然后,如果用户一天只有一条记录,则需要弄清楚要显示的内容。
此外,当用户在一个日期办理登机手续并在另一个日期退房时,夜班会发生什么?
更好的解决方案是添加一个位列来指定记录是用于签入还是用于签出。
使用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)