Sql 使用函数和条件生成另外两列

Sql 使用函数和条件生成另外两列,sql,oracle,Sql,Oracle,输入表: 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 |

输入表:

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     |
所需输出:

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'

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

您在信函中说明了生成工作日的规则:

  • 如果该记录不是日期的最后一条记录,则NULL
  • 如果记录是日期的最后一条记录,但超时为空,则0
  • else1
这是针对特定问题的简化查询版本:

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

APC的答案略有不同,因为我对工作日规则的解释略有不同。。。这将给出您的预期输出。但似乎不符合你所说的规则:

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??
/
我调用了date列
dt
,以避免保留字,但尝试匹配您提供的内容

     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 

如果将进出时间存储为完整日期,而不是单独的(varchar2)列,那么这将更容易。现在还不清楚如果有人工作超过午夜会发生什么或应该发生什么,因此
超时时间似乎早于
时间in

关于如何减去时间部分以获得小时数的两个示例,如上述示例所示。不清楚你是如何获得工作日的。我想你可以把工作时间除以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
    ))
  /

你应该考虑更改问题的标题。此外,您应该尝试用纯文本表达问题。
timein
timeout
的数据类型是什么?varchar2?第三行使问题复杂化。请解释您的要求,而不是发布一些模糊的代码,让我们猜测它应该做什么。timein和timeout的数据类型是varchar2。在这里,我需要让working days字段显示为1date@Anish-如果这个答案解决了您的问题,您应该接受它。