Страницы

Поиск по вопросам

понедельник, 23 декабря 2019 г.

Объединить два запроса Oracle (Добавить строку итогов в запрос)

#sql #oracle


Есть два относительно одинаковых запроса. Второй запрос выводит суммарные данные первого.
Нельзя ли как-то их оптимизировать и выполнять все в одном запросе? И выводить сумму
в конце каждого столбца? 

Основной запрос:

select round(hz,2) HZ,bz,round(h0,1)HO,naim,
 round(sum(pf),2) PF,round(sum(pt),2) PT,
 round(sum(pdm),2) PDM,round(sum(pdp),2) PDP,round(sum(pbm),2)PBM,round(sum(pbp),2) PBP,
 round(sum(tp)/60,2) TP,round(sum(pf)/sum(tp)*60,1)SFP
 from (select r.hz,r.bz,r.h0,m.naim,r.pf,r.pt,r.pdm,r.pdp,r.pbm ,r.pbp,
 case when ((r.tz-p.ts)*1440 < 10) and ((r.i_rez3/60) < 10) then (case when r.n >
1 then ((r.ts-p.ts)*1440) else ((r.ts-r.tz)*1440) end)
 when ((r.tz-p.ts)*1440 > 10) and ((r.i_rez3/60) < 10) then (case when r.n > 1 then
(((r.ts-r.tz)*1440)+10) else((r.ts-r.tz)*1440)end) 
 when ((r.tz-p.ts)*1440 < 10) and ((r.i_rez3/60) > 10) then (case when r.n > 1 then
((((r.ts-p.ts)*1440)-(r.i_rez3/60-10)))else((((r.ts-r.tz)*1440)-(r.i_rez3/60-10))) end)
 when ((r.tz-p.ts)*1440 > 10) and ((r.i_rez3/60) > 10) then (case when r.n > 1 then
((((r.ts-r.tz))*1440+10-(r.i_rez3/60-10))) else((((r.ts-r.tz))*1440-(r.i_rez3/60-10)))end)
end as tp
 from zxp.rulon r,zxp.mc m,zxp.rulon p
 where
r.ts between to_date('14.04.16 22:00:00','dd.mm.yy hh24:mi:ss') and to_date('15.04.16
7:00:00','dd.mm.yy hh24:mi:ss')+1 
  and r.ms = m.ukey
 and p.ts = (
   select max(pp.ts)
   from zxp.rulon pp 
   where pp.ts <= r.tz 
     and pp.ts > r.tz-1))
 group by hz,h0,bz,naim
 order by hz,h0,bz,naim


Дублирующий с суммой: 

select 'Итого:',round(sum(pf),2)"Р физ.",round(sum(pt),2)"Р теор.",
 round(sum(pdm),2)"Р доп. -",round(sum(pdp),2)"Р доп. +",round(sum(pbm),2)"Р бр.
-",round(sum(pbp),2)"Р бр. +",
 round(sum(tp)/60,2)"Длит.",round(sum(pf)/sum(tp)*60,1)"Произв."
 from (select 
 r.pf,r.pt,r.pdm,r.pdp,r.pbm,r.pbp,
 case when ((r.tz-p.ts)*1440 < 10) and ((r.i_rez3/60) < 10) then (case when r.n >
1 then ((r.ts-p.ts)*1440) else ((r.ts-r.tz)*1440) end)
 when ((r.tz-p.ts)*1440 > 10) and ((r.i_rez3/60) < 10) then (case when r.n > 1 then
(((r.ts-r.tz)*1440)+10) else((r.ts-r.tz)*1440)end) 
 when ((r.tz-p.ts)*1440 < 10) and ((r.i_rez3/60) > 10) then (case when r.n > 1 then
((((r.ts-p.ts)*1440)-(r.i_rez3/60-10)))else((((r.ts-r.tz)*1440)-(r.i_rez3/60-10))) end)
 when ((r.tz-p.ts)*1440 > 10) and ((r.i_rez3/60) > 10) then (case when r.n > 1 then
((((r.ts-r.tz))*1440+10-(r.i_rez3/60-10))) else((((r.ts-r.tz))*1440-(r.i_rez3/60-10)))end)
end as tp
 from zxp.rulon r,zxp.rulon p
 where     r.ts between to_date('14.04.16 22:00:00','dd.mm.yy hh24:mi:ss') and to_date
('15.04.16 7:00:00','dd.mm.yy hh24:mi:ss')  and 
 p.ts =(select max(pp.ts) from zxp.rulon pp where pp.ts <= r.tz and pp.ts > r.tz-1))

    


Ответы

Ответ 1



Используйте функцию ROLLUP при группировке, она умеет подводить промежуточные итоги по указанным колонкам. Если нам нужен итог только по части колонок из group by, то оставшиеся следует заключить в дополнительные скобки. Т.к. вы хотите получить только общий итог - то все колонки надо заключить в дополнительные скобки в rollup. Примерно так: select round(hz,2) HZ,bz,round(h0,1)HO,naim, ..... from ... group by ROLLUP((hz,h0,bz,naim)) --<---- Колонки в двойных скобках для общего итога !!! order by hz,h0,bz,naim В итоговой записи все колонки указанные к группировке будут иметь значение NULL, что можно использовать для вывода надписей 'Итого' и т.п. Или используйте функцию grouping(колонка) которая вернет 1 - если данная строка итог или 0 - если это строка данных.

Комментариев нет:

Отправить комментарий