sql >> データベース >  >> RDS >> Oracle

OracleSQLの営業時間に基づいて時間を計算する

    時間の差を直接計算できます:

    SELECT task,
           start_time,
           end_time,
           ROUND(
             (
               -- Calculate the full weeks difference from the start of ISO weeks.
               ( TRUNC( end_time, 'IW' ) - TRUNC( start_time, 'IW' ) ) * (10/24) * (6/7)
               -- Add the full days for the final week.
               + LEAST( TRUNC( end_time ) - TRUNC( end_time, 'IW' ), 6 ) * (10/24)
               -- Subtract the full days from the days of the week before the start date.
               - LEAST( TRUNC( start_time ) - TRUNC( start_time, 'IW' ), 6 ) * (10/24)
               -- Add the hours of the final day
               + LEAST( GREATEST( end_time - TRUNC( end_time ) - 8/24, 0 ), 10/24 )
               -- Subtract the hours of the day before the range starts.
               - LEAST( GREATEST( start_time - TRUNC( start_time ) - 8/24, 0 ), 10/24 )
             )
             -- Multiply to give minutes rather than fractions of full days.
             * 24,
             15 -- Number of decimal places
           ) AS work_day_hours_diff
    FROM   your_table;
    

    サンプルデータの場合:

    CREATE TABLE your_table ( TASK, START_TIME, END_TIME ) AS
    SELECT 'A', DATE '2017-01-16' + INTERVAL '10:00' HOUR TO MINUTE, DATE '2017-01-23' + INTERVAL '11:35' HOUR TO MINUTE FROM DUAL UNION ALL
    SELECT 'B', DATE '2017-01-18' + INTERVAL '17:53' HOUR TO MINUTE, DATE '2017-01-19' + INTERVAL '08:00' HOUR TO MINUTE FROM DUAL UNION ALL
    SELECT 'C', DATE '2017-01-13' + INTERVAL '13:00' HOUR TO MINUTE, DATE '2017-01-17' + INTERVAL '14:52' HOUR TO MINUTE FROM DUAL UNION ALL
    SELECT 'D', DATE '2017-01-21' + INTERVAL '10:00' HOUR TO MINUTE, DATE '2017-01-30' + INTERVAL '08:52' HOUR TO MINUTE FROM DUAL;
    

    出力(日付形式YYYY-MM-DD HH24:MI:SS (DY) ):

    TASK | START_TIME                | END_TIME                  | WORK_DAY_HOURS_DIFF
    :--- | :------------------------ | :------------------------ | ------------------:
    A    | 2017-01-16 10:00:00 (MON) | 2017-01-23 11:35:00 (MON) |  61.583333333333333
    B    | 2017-01-18 17:53:00 (WED) | 2017-01-19 08:00:00 (THU) |    .116666666666667
    C    | 2017-01-13 13:00:00 (FRI) | 2017-01-17 14:52:00 (TUE) |  31.866666666666667
    D    | 2017-01-21 10:00:00 (SAT) | 2017-01-30 08:52:00 (MON) |  68.866666666666667
    

    db<>ここでフィドル

    以前の解決策:

    相関階層クエリを使用して、就業日ごとに1つの行を生成し、各日の時間を合計することができます。

    SELECT task,
           COALESCE( SUM( end_time - start_time ), 0 ) * 24 AS total_hours
    FROM   (
      SELECT task,
             GREATEST( t.start_time, d.column_value + INTERVAL '8' HOUR ) AS start_time,
             LEAST( t.end_time, d.column_value + INTERVAL '18' HOUR ) AS end_time
      FROM   your_table t
             LEFT OUTER JOIN
             TABLE(
               CAST(
                 MULTISET(
                   SELECT TRUNC( t.start_time + LEVEL - 1 )
                   FROM   DUAL
                   WHERE  TRUNC( t.start_time + LEVEL - 1 ) - TRUNC( t.start_time + LEVEL - 1, 'iw' ) < 6
                   CONNECT BY TRUNC( t.start_time + LEVEL - 1 ) < t.end_time
                 ) AS SYS.ODCIDATELIST
               )
             ) d
             ON (   t.end_time   > d.column_value + INTERVAL  '8' HOUR
                AND t.start_time < d.column_value + INTERVAL '18' HOUR )
    )
    GROUP BY task;
    


    1. Oracleを使用してINTOを選択

    2. MySQLテーブルの重複を削除するにはどうすればよいですか?

    3. Postgres UNIQUE制約はインデックスを意味しますか?

    4. 同じテーブルの列に外部キー制約を適用します