Oracle - 多列和行的总和

时间:2016-12-14 15:03:34

标签: oracle

我有2张桌子

n_station val_horaires

n_station_table val_horaires

一个工作站有多个val_horaires,它们通过SUBSTR(code_mesure,1,4) = code_stas

链接

以下查询为我提供了来自特定组的所有电台,其中包含2个日期之间的所有值

select
  m.code_mesure,s.code_stas,s.nom_station, s.riviere_bassin, s.lambert_x, s.lambert_y,
  m.date_val_hor, m.h_01,m.h_02,m.h_03,m.h_04,m.h_05,m.h_06,m.h_07,m.h_08,m.h_09,m.h_10,m.h_11,m.h_12,m.h_13,m.h_14,m.h_15,m.h_16,m.h_17,m.h_18,m.h_19,m.h_20,m.h_21,m.h_22,m.h_23,m.h_24
from HYDRO.n_station s
join
(
  select 
    substr(vm.code_mesure,1,4) as code_stas, vm.*
  from HYDRO.val_horaires vm
  where code_mesure in (select code_mesure from HYDRO.GROUPE_MESURE where HYDRO.GROUPE_MESURE.CODE_GROUPE = 'TELEMP')
  AND vm.date_val_hor between '12/12/2016 16:00' AND '14/12/2016 17:00'
) m 
on m.code_stas = s.code_stas
where s.code_stas in (select SUBSTR(code_mesure,1,4) from HYDRO.GROUPE_MESURE where CODE_GROUPE = 'TELEMP')
AND s.lambert_x > 0 AND s.lambert_Y > 0

以上查询的结果

code_mesure code_stas nom_station           riviere_bassin          lambert_X lambert_Y date_val_hor      h_01 h_02 h_03 h_04 h_05 ...................................
70480015    7048    EREZEE                  OURTHE                  236667  109356  12/12/2016 00:00:00 0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
70480015    7048    EREZEE                  OURTHE                  236667  109356  13/12/2016 00:00:00 0   0   0   0   0   0   0   0   0   0,5 0   0,1 0,4 0,1 0   0   0   0   0   0   0   0   0   0
70480015    7048    EREZEE                  OURTHE                  236667  109356  14/12/2016 00:00:00 0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   -9999   -9999   -9999   -9999   -9999   -9999   -9999   -9999
60480015    6048    RACHAMPS-NOVILLE        OURTHE                  251592  86756   12/12/2016 00:00:00 0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
60480015    6048    RACHAMPS-NOVILLE        OURTHE                  251592  86756   13/12/2016 00:00:00 0   0   0   0   0   0   0   0   0   0   0,7 0   0   0   0   0   0   0   0,1 0   0   0   0   0
60480015    6048    RACHAMPS-NOVILLE        OURTHE                  251592  86756   14/12/2016 00:00:00 0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   -9999   -9999   -9999   -9999   -9999   -9999   -9999   -9999

我现在正试图为每个电台获取每一行的所有h_01,h_02,...h_24的和,并且还要汇总这3行合并。不应使用低于0的数字(例如:-9999

在这种情况下,结果将是

code_mesure code_stas nom_station           riviere_bassin          lambert_X lambert_Y Sum  LastValue
    70480015    7048    EREZEE                  OURTHE                  236667  109356  0.11 0
    60480015    6048    RACHAMPS-NOVILLE        OURTHE                  251592  86756   0.8  0

最后一件事:

如果开始日期为12/12/2016 16h00 - 日期12/12/2016的行中的值只能从h_16开始使用h_24

如果结束日期为14/12/2016 17:00 - 日期14/12/2016的行中的值只能从h_01开始使用h_17

1 个答案:

答案 0 :(得分:2)

使用GREATEST()将数字限制为正值,然后添加值以跨列组合,并使用SUM()聚合函数将行与GROUP BY子句组合。

WITH bounds ( start_time, end_time ) AS (
  SELECT TIMESTAMP '2016-12-12 16:00:00', TIMESTAMP '2016-12-14 17:00:00' FROM DUAL
)
select
  m.code_mesure,
  s.code_stas,
  s.nom_station,
  s.riviere_bassin,
  s.lambert_x,
  s.lambert_y,
  SUM(
      CASE WHEN m.date_val_hor +  1/24 BETWEEN b.start_time AND b.end_time THEN GREATEST( m.h_01, 0 ) ELSE 0 END 
    + CASE WHEN m.date_val_hor +  2/24 BETWEEN b.start_time AND b.end_time THEN GREATEST( m.h_02, 0 ) ELSE 0 END 
    + CASE WHEN m.date_val_hor +  3/24 BETWEEN b.start_time AND b.end_time THEN GREATEST( m.h_03, 0 ) ELSE 0 END 
    ...
    + CASE WHEN m.date_val_hor + 24/24 BETWEEN b.start_time AND b.end_time THEN GREATEST( m.h_24, 0 ) ELSE 0 END 
  ) AS h_sum,
  MAX(
    CASE EXTRACT( HOUR FROM b.end_time )
      WHEN  0 THEN m.h_01 -- Possibly m.h_24
      WHEN  1 THEN m.h_02 -- Possibly m.h_01
      WHEN  2 THEN m.h_03 -- Possibly m.h_02
      ...
      WHEN 22 THEN m.h_23 -- Possibly m.h_22
              ELSE m.h_24 -- Possibly m.h_23
    END
  ) KEEP ( DENSE_RANK LAST ORDER BY m.date_val_hor ) AS last_hour_value
from bounds b
     cross join
     HYDRO.n_station s
     join
     ( select substr(vm.code_mesure,1,4) as code_stas,
              vm.*
       from   HYDRO.val_horaires vm
              join
              bounds b
              ON ( vm.date_val_hor between TRUNC( b.start_time ) AND TRUNC( b.end_time ) )
       where  code_mesure in (select code_mesure
                              from   HYDRO.GROUPE_MESURE
                              where  HYDRO.GROUPE_MESURE.CODE_GROUPE = 'TELEMP')
      ) m 
      on m.code_stas = s.code_stas
where s.code_stas in ( select SUBSTR(code_mesure,1,4)
                       from   HYDRO.GROUPE_MESURE
                       where  CODE_GROUPE = 'TELEMP' )
AND s.lambert_x > 0 AND s.lambert_Y > 0
GROUP BY
  m.code_mesure,
  s.code_stas,
  s.nom_station,
  s.riviere_bassin,
  s.lambert_x,
  s.lambert_y