我有以下sql查询。
SELECT E.EMPID, TM.LOGIN, TM.LOGOUT,
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,TM.LOGIN,TM.LOGOUT
ORDER BY E.EMPID
运行上面的查询后,我得到以下输出:
EMPID LOGIN LOGOUT WORKEDHOURS
1 2-9-2013 9:30 2-9-2013 1:00 3:30
1 2-9-2013 2:00 2-9-2013 6:00 4:00
2 2-9-2013 9:30 2-9-2013 2:00 4:30
2 2-9-2013 3:00 2-9-2013 6:00 3:00
1 3-9-2013 9:30 3-9-2013 6:00 8:30
但是,我想显示结果如下,任何人请在这里帮忙,谢谢
EMPID LOGIN LOGOUT WORKEDHOURS
1 2-9-2013 9:30 2-9-2013 1:00 7:30
1 2-9-2013 2:00 2-9-2013 6:00
2 2-9-2013 9:30 2-9-2013 2:00 7:30
2 2-9-2013 3:00 2-9-2013 6:00
1 3-9-2013 9:30 3-9-2013 6:00 8:30
答案 0 :(得分:0)
SELECT T.EMPID, T.LOGIN, T.LOGOUT, X.WORKEDHOURS
FROM TIMING_DETAILS T
INNER JOIN
(SELECT EMPID, DATEPART(YEAR, TM.LOGIN) YEAR, DATEPART(MONTH, TM.LOGIN) MONTH, DATEPART(DAY, TM.LOGIN) DAY,
CAST(SUM(DATEDIFF(MINUTE,TM.LOGIN,TM.LOGOUT))/60 AS VARCHAR(MAX))
+ ':'
+ CAST(SUM(DATEDIFF(MINUTE,TM.LOGIN,TM.LOGOUT))%60 AS VARCHAR(MAX)) AS WORKEDHOURS
FROM TIMING_DETAILS TM
WHERE TM.LOGIN BETWEEN '2013-09-02' AND DATEADD(DAY, 1, '2013-09-03')
GROUP BY EMPID, DATEPART(YEAR, TM.LOGIN), DATEPART(MONTH, TM.LOGIN), DATEPART(DAY, TM.LOGIN)) X
ON X.EMPID = T.EMPID
AND DATEPART(YEAR, T.LOGIN) = X.YEAR
AND DATEPART(MONTH, T.LOGIN) = X.MONTH
AND DATEPART(DAY, T.LOGIN) = X.DAY
ORDER BY X.EMPID, X.YEAR DESC, X.MONTH DESC, X.DAY DESC
答案 1 :(得分:0)
SELECT E.EMPID, TM.LOGIN, TM.LOGOUT,WORKHOURS_TABLE.WORKEDHOURS
FROM EMPLOYEE_DETAILS E, TIMING_DETAILS TM ,
(SELECT EMPID,
concat(
sum(hour(timeDIFF(TM.LOGOUT, TM.LOGIN )))
+
sum(minute(timeDIFF(TM.LOGOUT, TM.LOGIN ))) div 60 ,
":" ,
sum(minute(timeDIFF(TM.LOGOUT, TM.LOGIN ))) % 60
)
AS WORKEDHOURS
FROM TIMING_DETAILS TM
GROUP BY EMPID) AS WORKHOURS_TABLE
WHERE E.EMPID = WORKHOURS_TABLE.EMPID AND E.EMPID=TM.EMPID
ORDER BY E.EMPID
输出可能是:
EMPID LOGIN LOGOUT WORKEDHOURS
1 2-9-2013 9:30 2-9-2013 1:00 7:30
1 2-9-2013 2:00 2-9-2013 6:00 7:30
2 2-9-2013 9:30 2-9-2013 2:00 7:30
2 2-9-2013 3:00 2-9-2013 6:00 7:30
如果您想按日期分组,则必须为date
和time
分别保留一列,然后您可以按日期分组。
我在我的MySQL数据库中尝试了查询,它运行正常。你试试看。
答案 2 :(得分:0)
试试这个 -
SELECT
t.EMPID
, t.LOGIN
, t.LOGOUT
, WORKEDHOURS = CASE WHEN rn = 1 THEN t.WORKEDHOURS END
FROM (
SELECT
TM2.EMPID
, TM2.LOGIN
, TM2.LOGOUT
, TM.WORKEDHOURS
, rn = ROW_NUMBER() OVER (PARTITION BY TM2.EMPID ORDER BY TM2.EMPID)
FROM dbo.TIMING_DETAILS TM2
JOIN (
SELECT
EMPID
, WORKEDHOURS = CAST(SUM(DATEDIFF(MINUTE, [login], LOGOUT)) / 60 AS VARCHAR(100)) + ':' + CAST(SUM(DATEDIFF(MINUTE, [login], LOGOUT)) % 60 AS VARCHAR(10))
FROM dbo.TIMING_DETAILS
WHERE [login] BETWEEN '20130902' AND '20130904'
GROUP BY EMPID
) TM ON TM2.EMPID = TM.EMPID
WHERE EXISTS( -- maybe this is unnecessary
SELECT 1
FROM dbo.EMPLOYEE_DETAILS E
WHERE E.EMPID = TM2.EMPID
)
) t
答案 3 :(得分:0)
在我们的对话之后,以及与其他参与者一起审核您的对话时,我发现您的问题稍微受到限制。你真正想要的输出是这样的:
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
同样,我还没有能力测试这个查询。
TESTED CASE:对Visual Studio 2010中本地SQL Server Express数据库的查询
我今天无法在Sql Server上进行测试,但这是我在本地Sql Server Express数据库上在Visual Studio 2010下测试的查询版本。
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。哦,我还必须明确地向NVARCHAR投入WorkedHours。
请根据您的环境进行相应调整。
希望这有帮助。