Страницы

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

вторник, 27 ноября 2018 г.

Объединить два запроса 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))


Ответ

Используйте функцию 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 - если это строка данных.

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

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