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),你可以使用convert
到char(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)
然后你需要弄清楚如果用户一天只有一条记录,你想显示什么。
此外,当用户在一个日期签到并在另一天签出时,夜班会发生什么情况?
更好的解决方案是添加一个位列来指定记录是用于签入还是签出。
更新
使用 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)
我有一个 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),你可以使用convert
到char(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)
然后你需要弄清楚如果用户一天只有一条记录,你想显示什么。
此外,当用户在一个日期签到并在另一天签出时,夜班会发生什么情况?
更好的解决方案是添加一个位列来指定记录是用于签入还是签出。
更新
使用 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)