SQL sum列由其他“dislocated”列聚合

时间:2017-11-08 10:13:04

标签: sql oracle aggregation

如果你能解决这个问题,我将非常感激。

我有这个Oracle SQL查询的结果,是关于夜班时间表的。

start_day_hours是班次start_date和午夜之间的总工作时间。 end_day_hours是午夜和轮班结束之间的总工作时间。

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)

非常感谢你的帮助!

4 个答案:

答案 0 :(得分:1)

SQL Fiddle

Oracle 11g 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 |

答案 1 :(得分:0)

一种简单的方法是将import React, { Component } from 'react'; import { connect } from 'react-redux'; import BigProfile from './components/bigProfile'; import fetchStudents from './actions/fetch'; import BigButton from './components/bigButton'; import ProfileListContainer from './components/profileListContainer'; export class App extends Component { constructor(props) { super(props); this.state = { studentName: '' }; } pickStudent(array) { var index = Math.floor(Math.random() * array.length); var student = array[index]; var studentName = student.name; this.setState({ studentName: student.name }); this['studentName'] = studentName; console.log(studentName); } componentWillMount() { this.props.fetchStudents(); } render() { const { students } = this.props; return ( <div className="App"> <BigProfile name={this['studentName']} /> <BigButton onClick={() => this.pickStudent(selectStudentGroup(students, pickColor()))} /> <ProfileListContainer /> </div> ); } } const mapStateToProps = store => { return { students: store.students }; }; export default connect(mapStateToProps, { fetchStudents })(App);合并为1列,将start/end date合并到其他列,start_hours/end_hours trunc列,date日期并计算{{ 1 {} group by列,如下所示。

sum

<强>结果:

hours

<强> DEMO

答案 2 :(得分:0)

非常感谢你的帮助@ MT0。最后我做到了这一点:

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

答案 3 :(得分:-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