SQL查询时间输入/输出

时间:2014-06-16 04:51:56

标签: sql sql-server-2005

我有一个包含以下示例输出的表格。

    ID_Emp| Name    |   Date
   ----------------------------------
    11    |Jonh     |14/05/2014 8:16
    11    |Jonh     |14/05/2014 13:35
    11    |Jonh     |14/05/2014 17:23
    11    |Jonh     |14/05/2014 21:09
    12    |Elizabe  |14/05/2014 14:06
    12    |Elizabe  |14/05/2014 22:39
    13    |Jimmy    |14/05/2014 8:00
    13    |Jimmy    |14/05/2014 17:12

我想构建一个查询来实现以下结果:

    ID_Emp|Name  |Date          |TimeIn |TimeOut|Hours
   -------------------------------------------------------
    11  |Jonh    |14/05/2014    |8:16   |13:35  |5:19
    11  |Jonh    |14/05/2014    |17:23  |21:09  |3:46
    12  |Elizabe |14/05/2014    |14:06  |22:39  |8:33
    13  |Jimmy   |14/05/2014    |8:00   |17:12  |9:12

4 个答案:

答案 0 :(得分:6)

试试这个:

;with cte as
(select *, rank() over(partition by ID_Emp order by [Date]) rn
 from attendance)

select src.ID_Emp, src.Name, convert(date, src.[Date]) as [Date],
concat(datepart(hour,src.[Date]),':',datepart(minute,src.[Date])) as [TimeIn],
concat(datepart(hour,tgt.[Date]),':',datepart(minute,tgt.[Date])) as [TimeOut],
concat(datediff(minute,src.[Date],tgt.[Date])/60,':',datediff(minute,src.[Date],tgt. [Date])%60) as [Hours]
from cte src
inner join cte tgt on src.ID_Emp = tgt.ID_Emp and src.rn + 1 = tgt.rn and src.rn % 2 = 1

警告:我仅在SQL Server 2008 R2上对此进行了测试,但我认为它应该适用于Oracle以及适当的修改。

说明:我们使用RANK函数按每个ID_Emp的日期和时间排序。然后,我们加入ID并获得成对行。最后,为了确保我们不选择每对连续行,我们要求源行的排名应为奇数。

答案 1 :(得分:1)

尝试此查询:

   WITH Level1
           AS (-- apply row numbers 
               SELECT ID_Emp , 
                      Name,
                      CAST(Date AS DATETIME) AS [DateTime] , 
                     ROW_NUMBER() OVER ( PARTITION BY ID_Emp 
                                  ORDER BY Date ) AS RowNum 
              FROM table1 
              ), 
        LEVEL2
           AS (-- find the last and next event type for each row 
              SELECT   A.ID_Emp , 
                       A.Name,
                       A.DateTime ,                       
                       COALESCE(NULL, 'N/A') AS LastEvent , 
                       COALESCE(NULL, 'N/A') AS NextEvent 
              FROM Level1 A 
                   LEFT JOIN Level1 LastVal 
                      ON A.ID_Emp = LastVal.ID_Emp 
                         AND A.RowNum - 1 = LastVal.RowNum 
                   LEFT JOIN Level1 NextVal 
                      ON A.ID_Emp = NextVal.ID_Emp 
                         AND A.RowNum + 1 = NextVal.RowNum ), 
        Level3 
           AS (-- reapply row numbers to row-eliminated set 
              SELECT  ID_Emp ,
                      Name,
                      DateTime ,                      
                      LastEvent , 
                      NextEvent , 
                      ROW_NUMBER() OVER ( PARTITION BY ID_Emp 
                          ORDER BY DateTime ) AS RowNBr 
              FROM Level2              
              ), 
        Level4
           AS (-- pair enter and exit rows. 
               SELECT A.ID_Emp , 
                      A.Name,
                      A.DateTime , 
                      B.DateTime AS ExitDateTime 
               FROM Level3 A 
                    JOIN Level3 B ON A.ID_Emp = B.ID_Emp 
                                     AND A.RowNBr + 1 = B.RowNBr               
               ), 
        LEVEL5 
           AS (--Calculate the work session duration 
               SELECT ID_Emp , 
                      Name,
                      DATEDIFF(second, DateTime, ExitDateTime) 
                               AS Seconds , 
                      DateTime , 
                      ExitDateTime 
               FROM Level4
              ) 


  SELECT ID_Emp , 
          Name,
          CAST([DateTime] AS Date) AS [Date],
          CONVERT(varchar(5), [DateTime], 108) as [In], 
          CONVERT(varchar(5), [ExitDateTime], 108) As Out,  
          RIGHT('0' +   CAST(Seconds / 3600 AS VARCHAR(2)), 2) + ':' 
          + RIGHT('0' +   CAST(Seconds % 3600 / 60 AS VARCHAR(2)), 2) + ':' 
          + RIGHT('0' +   CAST(Seconds % 3600 % 60 AS VARCHAR(2)), 2) 
                               AS TotalHours 
   FROM Level5;

<强> Live Demo

输出:


ID_EMP  NAME    DATE        IN                  OUT                 TOTALHOURS

11      Jonh    2014-05-14  08:16:00.0000000    13:35:00.0000000    05:19:00
12      Elizabe 2014-05-14  14:06:00.0000000    22:39:00.0000000    08:33:00
13      immy    2014-05-14  08:00:00.0000000    17:12:00.0000000    09:12:00

答案 2 :(得分:1)

某些记录中存在重复:以下是我的查询

SELECT * FROM emp_atten
WITH Level1
       AS (-- apply row numbers 
           SELECT  empid ,
                  CAST(DATTIME AS DATETIME) AS [DateTime] , 
                ROW_NUMBER() OVER ( PARTITION BY empid 
                                    ORDER BY G_DATE ) AS RowNum,attendance
          FROM emp_atten 
          ), 
    LEVEL2
       AS (-- find the last and next event type for each row 
          SELECT   A.empid , 
                   A.DateTime ,                       
                   COALESCE(NULL, 'N/A') AS LastEvent , 
                   COALESCE(NULL, 'N/A') AS NextEvent,
                   A.attendance 
          FROM Level1 A 
               LEFT JOIN Level1 LastVal 
                  ON A.empid = LastVal.empid 
                     AND A.RowNum - 1 = LastVal.RowNum  
               LEFT JOIN Level1 NextVal 
                  ON A.empid = NextVal.empid 
                     AND A.RowNum + 1 = NextVal.RowNum ), 
    Level3 
       AS (-- reapply row numbers to row-eliminated set 
          SELECT  empid ,
                  DateTime ,                      
                  LastEvent , 
                  NextEvent , 
                  ROW_NUMBER() OVER ( PARTITION BY empid 
                                      ORDER BY DateTime ) AS RowNBr,
                      attendance 
          FROM Level2              
          ), 
    Level4
       AS (-- pair enter and exit rows. 
           SELECT A.empid , 
                  A.DateTime , 
                  B.DateTime AS ExitDateTime 
           FROM Level3 A 
                JOIN Level3 B ON A.empid = B.empid 
                    AND A.RowNBr + 1 = B.RowNBr AND B.attendance='OUT'      
           ), 
    LEVEL5 
       AS (--Calculate the work session duration 
           SELECT empid , 
                  DATEDIFF(second, DateTime, ExitDateTime) 
                           AS Seconds , 
                  DateTime , 
                  ExitDateTime 
           FROM Level4
          ) 


SELECT empid , 
      CAST([DateTime] AS Date) AS [Date],
      CONVERT(varchar(5), [DateTime], 108) as [In], 
      CONVERT(varchar(5), [ExitDateTime], 108) As Out,  
      RIGHT('0' +   CAST(Seconds / 3600 AS VARCHAR(2)), 2) + ':' 
      + RIGHT('0' +   CAST(Seconds % 3600 / 60 AS VARCHAR(2)), 2) + ':' 
      + RIGHT('0' +   CAST(Seconds % 3600 % 60 AS VARCHAR(2)), 2) 
                           AS TotalHours 
FROM Level5;

答案 3 :(得分:0)

以下是带有测试数据的Oracle查询:

WITH EMP_tABLE AS
(
SELECT A.*, 
RANK() OVER (PARTITION BY IDD ORDER BY DATEE) RANKK
FROM (
SELECT '11' IDD,  'Jonh' NAMEE ,  TO_DATE('14/05/2014 8:16', 'DD/MM/YYYY HH24:MI') DATEE FROM DUAL
UNION 
SELECT '11' IDD,  'Jonh' NAMEE  ,  TO_DATE('14/05/2014 13:35', 'DD/MM/YYYY HH24:MI') DATEE FROM DUAL
UNION 
SELECT '11' IDD,  'Jonh' NAMEE  ,  TO_DATE('14/05/2014 17:23', 'DD/MM/YYYY HH24:MI') DATEE FROM DUAL
UNION 
SELECT '11' IDD,  'Jonh' NAMEE  ,  TO_DATE('14/05/2014 21:09', 'DD/MM/YYYY HH24:MI') DATEE FROM DUAL

UNION 
SELECT '12' IDD,  'Elizabe' NAMEE  ,  TO_DATE('14/05/2014 14:06', 'DD/MM/YYYY HH24:MI') DATEE FROM DUAL
UNION 
SELECT '12' IDD,  'Elizabe' NAMEE  ,  TO_DATE('14/05/2014 22:39', 'DD/MM/YYYY HH24:MI') DATEE FROM DUAL
UNION 
SELECT '13' IDD,  'Jimmy' NAMEE  ,  TO_DATE('11/05/2014 8:00', 'DD/MM/YYYY HH24:MI') DATEE FROM DUAL
UNION 
SELECT '13' IDD,  'Jimmy' NAMEE  ,  TO_DATE('11/05/2014 17:12', 'DD/MM/YYYY HH24:MI') DATEE FROM DUAL
) A )
SELECT AA.IDD, AA.NAMEE,
TO_CHAR(AA.DATEE, 'DD/MM/YYYY') DATE_ONLY, TO_CHAR(AA.DATEE,'HH24:MI') TIME_IN, TO_CHAR(BB.DATEE,'HH24:MI') TIME_OUT,

TRUNC (MOD ( (BB.DATEE-AA.DATEE)*24*60*60 , (24*60*60)) / (60 * 60))   || ':' ||
       TRUNC (MOD ((BB.DATEE-AA.DATEE)*24*60*60, (60*60)) / 60)             
DURATION

FROM EMP_TABLE AA, EMP_TABLE BB
WHERE
AA.IDD = BB.IDD and AA.RANKK + 1 = BB.RANKK 
and MOD(AA.RANKK , 2) = 1 ;

以下是您使用的查询。

MY_TABLE, IDD, NAMEE, DATEE替换为相应的表格/字段名称。

 WITH EMP_tABLE AS
(
SELECT my_table.*, 
RANK() OVER (PARTITION BY IDD ORDER BY DATEE) RANKK
FROM my_table
)
SELECT AA.IDD, AA.NAMEE,
TO_CHAR(AA.DATEE, 'DD/MM/YYYY') DATE_ONLY, TO_CHAR(AA.DATEE,'HH24:MI') TIME_IN, TO_CHAR(BB.DATEE,'HH24:MI') TIME_OUT,

TRUNC (MOD ( (BB.DATEE-AA.DATEE)*24*60*60 , (24*60*60)) / (60 * 60))   || ':' ||
       TRUNC (MOD ((BB.DATEE-AA.DATEE)*24*60*60, (60*60)) / 60)             
DURATION

FROM EMP_TABLE AA, EMP_TABLE BB
WHERE
AA.IDD = BB.IDD and AA.RANKK + 1 = BB.RANKK 
and MOD(AA.RANKK , 2) = 1