2017-11-08 15 views
0

この問題を解決する助けがあれば非常に感謝します。他の人が "dislocated"カラムで集計したSQLの合計カラム

私はOracle SQLクエリのこの結果を持っています、夜間のスケジュールについてです。

start_day_hoursは、シフト開始日から午前0時までの勤務時間の合計です。 end_day_hoursは、午前0時から終了までの勤務時間の合計です。

start   midnight   end    start_day_hours  end_day_hours 
02/10/17 21:33 02/10/17 23:59 03/10/17 00:42  2,43    0,71 
03/10/17 21:34 03/10/17 23:59 04/10/17 00:19  2,42    0,32 
04/10/17 21:59 04/10/17 23:59 05/10/17 55:36  2,00    0,92 
16/10/17 21:59 16/10/17 23:59 17/10/17 00:01  2,00    0,01 
18/10/17 22:50 18/10/17 23:59 19/10/17 00:25  1,16    0,42 
19/10/17 22:19 19/10/17 23:59 20/10/17 01:00  1,67    1,01 

私は、日によってのようなものstart_day_hoursとend_day_hoursの合計を必要とする:あなたの助けのおかげで多くのことを

day   total_hours 
02/10/17   2,43 (2,43) 
03/10/17   3,13 (0.71+2,42) 
04/10/17   2,32 (0.32+2.00) 
05/10/17   0,92 (0,92) 
16/10/17   2,00 (2,00) 
17/10/17   0,01 (0,01) 
18/10/17   1,16 (1,16) 
19/10/17   2,51 (0.42+1.67) 
20/10/17   1,01 (1,01) 

を!

+0

_Columns_、_fields_です。 – jarlh

+0

ありがとう!、何の間違い! – Madmartigan

+0

真夜中は「23:59」ではありません。前日の終わりになるはずの毎日の開始に1分をかけます。 – MT0

答えて

1

SQL Fiddle

Oracleの11グラムR2スキーマのセットアップ

CREATE TABLE shift (
    "start" DATE, 
    "end" DATE 
); 

INSERT INTO shift 
SELECT TIMESTAMP '2017-10-02 21:33:00', TIMESTAMP '2017-10-03 00:42:00' FROM DUAL UNION ALL 
SELECT TIMESTAMP '2017-10-03 21:34:00', TIMESTAMP '2017-10-04 00:19:00' FROM DUAL UNION ALL 
SELECT TIMESTAMP '2017-10-04 21:59:00', TIMESTAMP '2017-10-05 00:55:00' FROM DUAL UNION ALL 
SELECT TIMESTAMP '2017-10-16 21:59:00', TIMESTAMP '2017-10-17 00:01:00' FROM DUAL UNION ALL 
SELECT TIMESTAMP '2017-10-18 22:50:00', TIMESTAMP '2017-10-19 00:25:00' FROM DUAL UNION ALL 
SELECT TIMESTAMP '2017-10-19 22:19:00', TIMESTAMP '2017-10-20 01:00:00' FROM DUAL; 

クエリ1

早いstartと最新endの間、毎日取得するには、行の発電機を使用し、その日がシフトと重なったときに元のテーブルに結合し、それらの重なりを集計します。

WITH days (dt) AS (
    SELECT min_dt + LEVEL - 1 
    FROM (
    SELECT TRUNC(MIN("start")) AS min_dt, 
      TRUNC(MAX("end")) AS max_dt 
    FROM shift 
) 
    CONNECT BY min_dt + LEVEL - 1 <= max_dt 
) 
SELECT dt, 
     SUM(
     LEAST("end", dt + INTERVAL '1' DAY) 
     - GREATEST("start", dt) 
     ) * 24 AS hours_worked 
FROM shift s 
     INNER JOIN days d 
     ON ( s."start" < d.dt + INTERVAL '1' DAY 
      AND s."end" > d.dt) 
GROUP BY dt 
ORDER BY dt 

Results

|     DT |   HOURS_WORKED | 
|----------------------|----------------------| 
| 2017-10-02T00:00:00Z |     2.45 | 
| 2017-10-03T00:00:00Z | 3.1333333333333333 | 
| 2017-10-04T00:00:00Z | 2.3333333333333335 | 
| 2017-10-05T00:00:00Z | 0.9166666666666666 | 
| 2017-10-16T00:00:00Z | 2.0166666666666666 | 
| 2017-10-17T00:00:00Z | 0.016666666666666666 | 
| 2017-10-18T00:00:00Z | 1.1666666666666667 | 
| 2017-10-19T00:00:00Z |     2.1 | 
| 2017-10-20T00:00:00Z |     1 | 
+0

助けてくれてありがとう@ MT0 – Madmartigan

-1
SELECT T1.START_DATE,nvl(T1.START_DAY_HOURS,0) + nvl(T2.END_DAY_HOURS,0) TOTAL_HOURS 
FROM 
(SELECT TRUNC(START) START_DATE,sum(nvl(START_DAY_HOURS,0)) START_DAY_HOURS FROM YOUR_TABLE GROUP BY TRUNC(START)) T1 

LEFT JOIN (SELECT TRUNC(END) END_DATE,SUM(nvl(END_DAY_HOURS,0)) END_DAY_HOURS FROM YOUR_TABLE GROUP BY TRUNC(END)) T2 
ON T1.START_DATE = T2.END_DATE 
+0

1日あたり2シフト以上の場合には値を集計しないで、最後の行を逃すように見えます(その日にシフトが終わったときのみ)。 – MT0

+0

最後の行だけでなく、対応する開始日のない終了日がある毎日欠場します。また、対応する終了日がない開始日がある場合、合計時間は「NULL」になります。 – MT0

+0

攻撃的ではありませんが、私のSQLでフィード開発者をスプーンしようとしていません。彼らが自分で調べることができる方向性をここに示すようにしようとしています。しかし、あなたの謙虚な要求でSQLを変更しました。ありがとうございます。 – AK47

0

一つの簡単な方法は、他の列、truncdateコラム、group by日に1列とstart_hours/end_hoursに組合start/end dateになるとsumhoursの列を計算することができ以下のように。

SELECT date1 AS DAY, 
     sum(hours) AS total_hours 
FROM 
    (SELECT trunc(start1) AS date1, 
      start_day_hours AS hours 
    FROM t1 
    UNION ALL 
    SELECT trunc(end1), 
      end_day_hours 
    FROM t1) t 
GROUP BY date1 
ORDER BY date1; 

結果:あなたの助けする@ MT0ため

DAY     TOTAL_HOURS 
--------------------------------- 
02.10.2017 00:00:00 2,43 
03.10.2017 00:00:00 3,13 
04.10.2017 00:00:00 2,32 
05.10.2017 00:00:00 0,92 
16.10.2017 00:00:00 2 
17.10.2017 00:00:00 0,01 
18.10.2017 00:00:00 1,16 
19.10.2017 00:00:00 2,09 
20.10.2017 00:00:00 1,01 

DEMO

0

おかげで多くのことを。最後に私はこれをしました:

SELECT dt, 
    NVL(SUM(
    LEAST(SIXTY, dt + INTERVAL '1' DAY) 
    - GREATEST(ZERO, dt) 
    ) * 24, 0.0) AS hours_worked 
FROM shitf s 
    RIGHT JOIN 
(SELECT TO_DATE('2017-10-01 00:00:00', 'YYYY/MM/DD HH24:MI:SS')+LEVEL-1 AS dt 
FROM DUAL CONNECT BY LEVEL <= TO_CHAR(LAST_DAY(TO_DATE('2017-10-01 00:00:00', 'YYYY/MM/DD HH24:MI:SS')),'DD')) d 
ON (s.ZERO < d.dt + INTERVAL '1' DAY 
     AND s.SIXTY > d.dt) 
GROUP dt 
ORDER dt 
+0

時間を少し費やしてくれた皆様に感謝します! – Madmartigan

関連する問題