select --install DATE_TRUNC('month', dayscale.dt)::date as m ,dayscale.dt::date ,siv.price as price_i ,siv.quantity as quantity_i ,siv0.price as price0_i ,siv0.quantity as quantity0_i ,a.is_actual as is_actual_i ,a.probability_perc as p_i ,(100-COALESCE(a.probability_perc,0)) as p_i_rest ,siv.specification_item_uid as si_uid_i ,siv.agreement_version as av_i ,siv0.specification_item_uid as si_uid0_i ,siv0.agreement_version as av0_i ,null as price_f ,null as quantity_f ,null as price0_f ,null as quantity0_f ,null as is_actual_f ,null as p_f ,null as p_f_rest ,null as cost_f ,null as cost_month_f ,null as dt_from_f ,null as dt_to_f ,null as dt_from0_f ,null as dt_to0_f ,null as si_uid_f ,null as av_f ,null as si_uid0_f ,null as av0_f from (SELECT dd::date as dt FROM generate_series( '#DAYSCALE_START#'::timestamp ,'#DAYSCALE_FINISH#'::timestamp ,'1 day'::interval) dd ) dayscale left outer join specification_item_version siv on (dayscale.dt=siv.dt_from) left outer join specification_item si on (siv.specification_item_uid=si.specification_item_uid AND si.pricing_model_id in (1)) left outer join specification s on (si.specification_id=s.specification_id) left outer join agreement a on (s.contract_id=a.contract_id AND siv.agreement_version=a.agreement_version AND a.agreement_version=(select max(iiv.agreement_version) from specification_item_version iiv join specification_item ii on (iiv.specification_item_uid=ii.specification_item_uid) join specification isp on (ii.specification_id=isp.specification_id) join agreement ia on (isp.contract_id=ia.contract_id AND iiv.agreement_version=ia.agreement_version) where iiv.specification_item_uid=si.specification_item_uid --AND ia.is_actual )) join contract d on s.contract_id=d.contract_id join contragent k on d.contragent_id=k.contragent_id join svc on (si.svc_id=svc.svc_id) left outer join agreement a0 on (s.contract_id=a0.contract_id AND a0.agreement_version=(select max(iiv.agreement_version) from specification_item_version iiv join specification_item ii on (iiv.specification_item_uid=ii.specification_item_uid) join specification isp on (ii.specification_id=isp.specification_id) join agreement ia on (isp.contract_id=ia.contract_id AND iiv.agreement_version=ia.agreement_version) where iiv.specification_item_uid=si.specification_item_uid AND ia.agreement_version < a.agreement_version AND ia.is_actual )) left outer join specification_item_version siv0 on (siv0.specification_item_uid=si.specification_item_uid AND siv0.agreement_version=a0.agreement_version AND (dayscale.dt=siv0.dt_from)) where 1=1 union all --fix and payg select DATE_TRUNC('month', dayscale.dt)::date as m ,dayscale.dt::date ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,case when (siv.dt_to > dayscale.dt OR siv.dt_to IS NULL) then siv.price /*до окончания свежей сделки она суммируется с прошлой актуальной по правилу вероятностей, считая вероятность актуальной за сделки за 1*/ else 0 /*по окончании свежей сделки она дает нулевой вклад*/ end ,case when (siv.dt_to > dayscale.dt OR siv.dt_to IS NULL) then siv.quantity /*до окончания свежей сделки она суммируется с прошлой актуальной по правилу вероятностей, считая вероятность актуальной за сделки за 1*/ else 0 /*по окончании свежей сделки она дает нулевой вклад*/ end ,case when (siv0.dt_to > dayscale.dt OR siv0.dt_to IS NULL) then siv0.price /*до окончания свежей сделки она суммируется с прошлой актуальной по правилу вероятностей, считая вероятность актуальной за сделки за 1*/ else 0 /*по окончании свежей сделки она дает нулевой вклад*/ end ,case when (siv0.dt_to > dayscale.dt OR siv0.dt_to IS NULL) then siv0.quantity /*до окончания свежей сделки она суммируется с прошлой актуальной по правилу вероятностей, считая вероятность актуальной за сделки за 1*/ else 0 /*по окончании свежей сделки она дает нулевой вклад*/ end ,a.is_actual as is_actual_f ,a.probability_perc as p_f ,(100-COALESCE(a.probability_perc,0)) as p_f_rest ,case when (siv.dt_to > dayscale.dt OR siv.dt_to IS NULL) then siv.price/dayscale.monthdays*siv.quantity*a.probability_perc/100 else 0 /*по окончании свежей сделки она дает нулевой вклад*/ end + COALESCE(case when (siv0.dt_to > dayscale.dt OR siv0.dt_to IS NULL) then siv0.price/dayscale.monthdays*siv0.quantity*(100- a.probability_perc)/100 else 0 /*по окончании свежей сделки она дает нулевой вклад*/ end,0) ,case when (siv.dt_to > dayscale.dt OR siv.dt_to IS NULL) then siv.price*siv.quantity*a.probability_perc/100 else 0 /*по окончании свежей сделки она дает нулевой вклад*/ end + COALESCE(case when (siv0.dt_to > dayscale.dt OR siv0.dt_to IS NULL) then siv0.price*siv0.quantity*(100- a.probability_perc)/100 else 0 /*по окончании свежей сделки она дает нулевой вклад*/ end,0) ,siv.dt_from ,siv.dt_to ,siv0.dt_from ,siv0.dt_to ,siv.specification_item_uid ,siv.agreement_version ,siv0.specification_item_uid ,siv0.agreement_version from (SELECT dd::date as dt , DATE_PART('days', DATE_TRUNC('month', dd) + '1 MONTH'::INTERVAL - '1 DAY'::INTERVAL) monthdays FROM generate_series( '#DAYSCALE_START#'::timestamp ,'#DAYSCALE_FINISH#'::timestamp ,'1 day'::interval) dd ) dayscale left outer join specification_item_version siv on (dayscale.dt >= siv.dt_from /*AND (siv.dt_to > dayscale.dt OR siv.dt_to IS NULL)*/ AND siv.agreement_version=(select max(iiv.agreement_version) from specification_item_version iiv join specification_item ii on (iiv.specification_item_uid=ii.specification_item_uid) join specification isp on (ii.specification_id=isp.specification_id) join agreement ia on (isp.contract_id=ia.contract_id AND iiv.agreement_version=ia.agreement_version) where iiv.specification_item_uid=siv.specification_item_uid AND (dayscale.dt >= iiv.dt_from /*AND (iiv.dt_to > dayscale.dt OR iiv.dt_to IS NULL)*/))) /*AND ia.is_actual*/ /*свежее соглашение не обязано быть действующим*/ join specification_item si on (siv.specification_item_uid=si.specification_item_uid AND si.pricing_model_id in (2,3)) join specification s on (si.specification_id=s.specification_id) join agreement a on (s.contract_id=a.contract_id AND a.agreement_version=siv.agreement_version) join contract d on s.contract_id=d.contract_id join contragent k on d.contragent_id=k.contragent_id join svc on (si.svc_id=svc.svc_id) -- находим предыдущее действующее соглашение -- если свежее соглашение действует, то впр -- нам нужно, чтобы в прошлом (до dt_from свежего соглашения) свежак был прозрачен, -- а в будущем (после dt_to) факт перетирался свежим соглашением left outer join agreement a0 on (s.contract_id=a0.contract_id AND a0.agreement_version=( select max(iiv.agreement_version) from specification_item_version iiv join specification_item ii on (iiv.specification_item_uid=ii.specification_item_uid) join specification isp on (ii.specification_id=isp.specification_id) join agreement ia on (isp.contract_id=ia.contract_id AND iiv.agreement_version=ia.agreement_version) where iiv.specification_item_uid=si.specification_item_uid AND ia.agreement_version < siv.agreement_version AND ia.is_actual /*именно действующее соглашение, принимаемое за факт*/ ) ) left outer join specification_item_version siv0 on (siv0.specification_item_uid=si.specification_item_uid AND siv0.agreement_version=a0.agreement_version AND (dayscale.dt >= siv0.dt_from /*AND (siv0.dt_to > dayscale.dt OR siv0.dt_to IS NULL)*/)) where 1=1 order by dt Выручка по дням 2023-01-01 .. 2029-12-31
#qRead.recordCount# записей
Дни и месяцы без данных не показаны. Инсталл и ежемес могут генерировать отдельные строки на один день. Вариант с локальной рабочей версией строки (инстанса)
Дата Инсталл рабочая Инсталл базовая Ежемес рабочая Ежемес базовая Ежемес
#dateFormat(dt,"YYYY-MM-DD")# (#myNumFmt(price_i)#*#quantity_i#*#p_i#%(#p_i_rest#%)
#myNumFmt(price0_i)#*#quantity0_i#
[#av_f#] #myNumFmt(price_f)#*#quantity_f#*#p_f#%(#p_f_rest#%) #dateFormat(dt_from_f,'YYYY-MM-DD')# - #dateFormat(dt_to_f,'YYYY-MM-DD')#
[#av0_f#] #myNumFmt(price0_f)#*#quantity0_f# #dateFormat(dt_from0_f,'YYYY-MM-DD')# - #dateFormat(dt_to0_f,'YYYY-MM-DD')#
#myNumFmt(cost_month_f)# | #myNumFmt(cost_f)#