0

我有以下 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
4

4 回答 4

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
于 2013-09-25T06:08:27.997 回答
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

如果要按日期分组,则必须为dateand保留单独的列time,然后可以按日期分组。

我已经在我的 MySQL 数据库中尝试了该查询,它工作正常。你试试看。

于 2013-09-25T06:03:25.197 回答
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

同样,我无法测试此查询。

测试案例:在 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。

请根据您的环境进行相应调整。

希望这可以帮助。

于 2013-09-26T06:20:06.770 回答
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
于 2013-09-25T05:58:42.877 回答