在我们的对话之后,并且还回顾了您与其他参与者的对话,我发现您的问题稍微受到限制。你真正想要的输出是这样的:
EMPID DAY WORKEDHOURS
1 2-9-2013 7:30
1 3-9-2013 8:30
2 2-9-2013 7:30
案例1:范围内的单日
如果您只对某一天感兴趣,那么您只需将日期插入结果中即可。请尝试以下方法:
SELECT E.EMPID,
'2013-09-02' AS DAY,
SUM(DATEDIFF(MINUTE,TM.LOGIN,TM.LOGOUT)/60)+':'+
SUM(DATEDIFF(MINUTE,TM.LOGIN,TM.LOGOUT)%60) AS WORKEDHOURS
FROM EMPLOYEE_DETAILS E
LEFT JOIN TIMING_DETAILS TM
ON (E.EMPID=TM.EMPID)
WHERE TM.LOGIN BETWEEN '2013-09-02' AND DATEADD(DAY, 1, '2013-09-03')
GROUP BY E.EMPID
ORDER BY E.EMPID
您还可以重写查询以使用命名参数来表示相关日期。这是一个示例,但要使用它,您必须将值绑定到参数TheDay
:
SELECT E.EMPID,
@TheDay AS DAY,
SUM(DATEDIFF(MINUTE,TM.LOGIN,TM.LOGOUT)/60)+':'+
SUM(DATEDIFF(MINUTE,TM.LOGIN,TM.LOGOUT)%60) AS WORKEDHOURS
FROM EMPLOYEE_DETAILS E
LEFT JOIN TIMING_DETAILS TM
ON (E.EMPID=TM.EMPID)
WHERE TM.LOGIN BETWEEN @TheDay AND DATEADD(DAY, 1, @TheDay)
GROUP BY E.EMPID
ORDER BY E.EMPID
案例2:范围内的多天
如果每个 EMPID 需要多行,但每天只需要一个这样的行,那么事情会更复杂。我认为在几个(也许是全部)DBMS 中是可能的,但可能需要使用不可移植的特性。我们需要做的是日期时间值GROUP BY
的天部分。LOGIN
如果您使用的是 SQL Server 2008(或更高版本),则可以尝试以下操作:
SELECT E.EMPID,
CAST(TM.LOGIN AS DATE) AS DAY,
SUM(DATEDIFF(MINUTE,TM.LOGIN,TM.LOGOUT)/60)+':'+
SUM(DATEDIFF(MINUTE,TM.LOGIN,TM.LOGOUT)%60) AS WORKEDHOURS
FROM EMPLOYEE_DETAILS E
LEFT JOIN TIMING_DETAILS TM
ON (E.EMPID=TM.EMPID)
WHERE TM.LOGIN BETWEEN '2013-09-02' AND DATEADD(DAY, 1, '2013-09-03')
GROUP BY E.EMPID, CAST(TM.LOGIN AS DATE)
ORDER BY E.EMPID
请注意,我无法测试此查询。例如,您可能不得不GROUP BY DAY
重复表达式而不是重复表达式。
案例 2B:范围内的多天,第一次和最后一次登录
您是否希望每个 EMPID 每天一行,但第一次登录时间和最后一次注销时间?您可以尝试以下方法:
SELECT E.EMPID,
MIN(TM.LOGIN) AS FIRSTLOGIN,
MAX(TM.LOGOUT) AS LASTLOGOUT,
SUM(DATEDIFF(MINUTE,TM.LOGIN,TM.LOGOUT)/60)+':'+
SUM(DATEDIFF(MINUTE,TM.LOGIN,TM.LOGOUT)%60) AS WORKEDHOURS
FROM EMPLOYEE_DETAILS E
LEFT JOIN TIMING_DETAILS TM
ON (E.EMPID=TM.EMPID)
WHERE TM.LOGIN BETWEEN '2013-09-02' AND DATEADD(DAY, 1, '2013-09-03')
GROUP BY E.EMPID, CAST(TM.LOGIN AS DATE)
ORDER BY E.EMPID
同样,我无法测试此查询。
测试案例:在 Visual Studio 2010 中对本地 SQL Server Express 数据库的查询
我今天无法在 Sql Server 上进行测试,但这是我在 Visual Studio 2010 下在本地 Sql Server Express 数据库上测试过的查询版本。
SELECT
E.EMPID, E.NAME,
MIN(TM.LOGIN) AS FirstLogIn,
MAX(TM.LOGOUT) AS LastLogOut,
CAST(SUM(DATEDIFF(MINUTE, TM.LOGIN, TM.LOGOUT) / 60) AS NVARCHAR)+':'+CAST(SUM(DATEDIFF(MINUTE, TM.LOGIN, TM.LOGOUT) % 60) AS NVARCHAR) AS WorkedHours
FROM
EMPLOYEE_DETAILS AS E LEFT OUTER JOIN TIMING_DETAILS AS TM ON E.EMPID = TM.EMPID
WHERE
TM.LOGIN BETWEEN '2013-09-21' AND DATEADD(DAY, 1, '2013-09-22')
GROUP BY
E.EMPID, E.NAME,
DATEADD(DAY, DATEDIFF(DAY, 0, TM.LOGIN), 0)
ORDER BY
E.EMPID, FirstLogin
测试数据 EMPLOYEE_DETAILS:
EMPID NAME
1 Joe
2 Jane
3 Martha
测试数据 TIMING_DETAILS:
EMPID LOGIN LOGOUT
1 '2013-09-21 09:00:00' '2013-09-21 10:30:00'
1 '2013-09-21 14:00:00' '2013-09-21 16:00:00'
1 '2013-09-22 08:30:00' '2013-09-22 11:00:00'
2 '2013-09-21 10:45:00' '2013-09-21 13:30:00'
结果:
EMPID NAME FirstLogIn LastLogOut WorkedHours
1 Joe '2013-09-21 09:00:00' '2013-09-21 16:00:00' 3:30
1 Joe '2013-09-22 08:30:00' '2013-09-22 11:00:00' 2:30
2 Jane '2013-09-21 10:45:00' '2013-09-21 13:30:00' 2:45
这对我来说似乎是正确的。我的 SQL Server Express 查询的唯一区别是它不提供 DATE 类型,因此我不得不修改 CAST。哦,我还必须为 WorkedHours 显式转换为 NVARCHAR。
请根据您的环境进行相应调整。
希望这可以帮助。