0

输入表:

store    | employee  | date             |  timein  | timeout |   
    1    |      A    |        1-jan-12  |  10:00   | 17:00   |
    1    |      A    |        1-jan-12  |  20:00   | 22:00   |
    2    |      B    |        1-jan-12  |  10:00   |  -      |
    2    |      B    |        1-jan-12  |  17:00   | 20:00   |
    2    |      B    |        2-jan-12  |  10:00   | 17:00   |
    3    |      C    |        1-jan-12  |  10:00   | 12:00   |
    3    |      C    |        1-jan-12  |  13:00   | 15:00   |
    3    |      C    |        1-jan-12  |  20:00   | 23:00   |

期望的输出:

store | employee | date      |  timein  | timeout | hours | working_days |
 1    |     A    | 1-jan-12  |  10:00   | 17:00   |   7   |              |
 1    |     A    | 1-jan-12  |  20:00   | 22:00   |   2   |        1     |
 2    |     B    | 1-jan-12  |  10:00   |  -      |   0   |              | 
 2    |     B    | 1-jan-12  |  17:00   | 20:00   |   5   |        0     | 
 2    |     B    | 2-jan-12  |  10:00   | 17:00   |   7   |        1     | 
 3    |     C    | 1-jan-12  |  10:00   | 12:00   |   2   |              | 
 3    |     C    | 1-jan-12  |  13:00   | 15:00   |   2   |              | 
 3    |     C    | 1-jan-12  |  20:00   | 23:00   |   3   |        1     |

我的查询是:

select 
      store, 
      employee,
      date,
      timein,
      timeout,
      cast(trim(trailing ':' from cast(timeout) as number)-trim(trailing ':' from cast(timein) as number) as number) as hours,
     case
      when timeout is null then 0 and
     end
from
      tableattend
where date between '1-jan-12' and '2-jan-12' and store between 'A' and 'C'

working_days字段将以这种方式显示,但无法获得创建上述结果的确切函数。请指导我。

4

3 回答 3

0

Slight variation on APC's answer because I interpreted the working days rule slightly differently... this gives your expected output. but doesn't seem to match the rules you stated:

select store, employee, dt, timein, timeout, hours,
    case when rn = 1 then decode(tmp_timeout, null, 0, 1) end as working_days
from (
    select store, employee, dt, timein, timeout,
          case when timeout is null then 0
          else extract (hour from to_dsinterval('0 ' || timeout || ':00')
              - to_dsinterval('0 ' || timein || ':00'))
          end as hours,
          first_value(timeout)
              over (partition by store, employee, dt
                  order by timeout nulls first) as tmp_timeout,
          row_number()
              over (partition by store, employee, dt
                  order by timein desc) as rn
    from tableattend
)
where dt between '1-jan-12' and '2-jan-12'
-- and store between 'A' and 'C' -- store is numeric??
/

I called the date column dt to avoid the reserved word, but otherwise tried to match what you supplied.

     STORE EMPLOYEE DT        TIMEIN TIMEOUT      HOURS WORKING_DAYS
---------- -------- --------- ------ ------- ---------- ------------
         1 A        01-JAN-12 10:00  17:00            7              
         1 A        01-JAN-12 20:00  22:00            2            1 
         2 B        01-JAN-12 10:00                   0              
         2 B        01-JAN-12 17:00  20:00            3            0 
         2 B        02-JAN-12 10:00  17:00            7            1 
         3 C        01-JAN-12 10:00  12:00            2              
         3 C        01-JAN-12 13:00  15:00            2              
         3 C        01-JAN-12 20:00  23:00            3            1 

This would be easier if you were storing time in and out as full dates rather than as separate (varchar2) columns. It isn't clear what would or should happen if someone worked past midnight, so the timeout would appear to be before the timein.

于 2013-03-07T10:04:21.207 回答
0

关于如何减去时间部分以获得小时数的几个示例,如上面的示例所示。不清楚你如何获得工作日。我认为您可以将工作时间除以 8 以获得工作日......所有示例都经过测试:

SELECT round((time_diff/3600)/24, 1) days
     , trunc(time_diff/3600) hrs
     , trunc(mod(time_diff, 3600) / 60) mnt
     , trunc(mod(time_diff, 3600) / 60 /60) sec
  FROM
  (
   SELECT time_in, time_out, (time_out-time_in)* 86400 time_diff
     FROM 
   (
    SELECT to_date('01-JAN-2012 17:00:00', 'DD-MON-YYYY HH24:MI:SS') time_out
         , to_date('01-JAN-2012 10:00:00', 'DD-MON-YYYY HH24:MI:SS') time_in
      FROM dual
   ))
   /

使用提取示例:

 Select time_in, time_out, time_diff,
        EXTRACT(DAY FROM time_diff) days,
        EXTRACT(HOUR FROM time_diff) hours,
        EXTRACT(MINUTE FROM time_diff) minutes,
        EXTRACT(SECOND FROM time_diff) seconds
   From
   (
    Select time_in, time_out, (time_out - time_in) time_diff
      From
     (
      Select CAST(to_date('01-JAN-2012 17:00:00', 'DD-MON-YYYY HH24:MI:SS') AS TIMESTAMP) time_out
           , CAST(to_date('01-JAN-2012 10:00:00', 'DD-MON-YYYY HH24:MI:SS') AS TIMESTAMP) time_in
         From dual
    ))
  /
于 2013-03-07T15:52:20.213 回答
0

您在评论中声明您生成 WORKING_DAYS 的规则是:

  • 如果记录不是 DATE 的最后一条记录,则为NULL
  • 如果记录是 DATE 的最后一条记录但 TIMEOUT 为空,则为0
  • 否则1

这是您的查询的简化版本,用于解决特定问题:

select date
       , timein 
       , timeout
       , case 
            when rn != 1 then null
            when timeout is null then 0
            else 1
          end as working_days
from ( select date
              , timein 
              , timeout
              , row_number() over partition by date order by timein desc ) rn
       from  tableattend
      where date between '1-jan-12' and '2-jan-12' 
      and store between 'A' and 'C' )
order by date, timein
于 2013-03-07T09:31:23.073 回答