EDIT
Это почти полностью переписанный ответ, который я получил до
Тем не менее, как упоминалось ранее, я бы потерял все скобки ... они просто делают ваш код намного более нечитаемым. Они действительно нужны только тогда, когда имя столбца конфликтует с зарезервированным словом в SQL.
Далее вам не нужно select
из select
в псевдоним ... и вам не нужно беспокоиться о получении дополнительных данных в промежуточных результатах. На самом деле вы должны только select
из select
, когда вы выполняете какие-то агрегаты или вычисления. Прекрасным примером может служить ваш y
..., где вы можете рассчитать базовый коэффициент для своих расчетов ... и затем полностью избавиться от CASE
s, например:
select
x.mdc_code, x.cal_month, x.cal_year, x.activity, y.scenario_id,
y.initiative_id, x.volume, x.rate, y.metric_to_be_applied, y.change,
x.volume + applied_volume as New_Volume_VolumeChange ,
x.rate * applied_volume as New_Rate_VolumeChange,
(x.volume + applied_volume)/x.rate as New_DemandHours_VolumeChange,
((x.volume + applied_volume)/x.rate)/176 as New_DemandFTE_VolumeChange,
x.volume + applied_rate as New_Volume_RateChange ,
x.rate * applied_rate as New_Rate_RateChange,
(x.volume)/(x.rate + applied_rate) as New_DemandHours_RateChange,
((x.volume)/(x.rate+ applied_rate))/176 as New_DemandFTE_RateChange
from
myp_activity x
inner join
( select
iif( metric_to_be_applied = 'Volume', change, null ) as applied_volume,
iif( metric_to_be_applied = 'Rate', change, null ) as applied_rate,
mdc_code, cal_month, cal_year, activity, scenario_id, initiative_id, metric_to_be_applied, change
from
myp_initiatives
) as y
on
x.mdc_code = y.mdc_code
and x.cal_month = y.cal_month
and x.cal_year = y.cal_year
and x.activity = y.activity
where
y.initiative_id=10001
Концептуально, это абсолютно уместно, однако, ваши требования означают, что простой CTE не может быть применен к проблеме ... насколько я могу судить. Это потому, что нет способа перебрать инициативы, которые я могу выработать. Вместо этого позвольте мне предложить функцию, которая будет агрегировать изменения так, как вам нужно (я думаю).
Однако обратите внимание на что-то важное. Я не знаю типы данных ваших столбцов, и поэтому эта функция объявляет все как int
, что Я уверен, что не правильно. Вам нужно будет отредактировать типы данных так, чтобы они соответствовали вашим *
.
create function AppliedInitiatives() returns
@t table
(
mdc_code int, --> note: you have to change all these types to match your data
cal_month int,
cal_year int,
cal_activity int,
scenario_id int,
initiative_id int,
volume int,
rate int,
metric_to_be_applied nvarchar( 32 ),
change int,
New_Volume_VolumeChange int,
New_Rate_VolumeChange int,
New_DemandHours_VolumeChange int,
New_DemandFTE_VolumeChange int,
New_Volume_RateChange int,
New_Rate_RateChange int,
New_DemandHours_RateChange int,
New_DemandFTE_RateChange int
) as
begin
declare
@applied_volume int, --> note: you have to change all these types to match your data
@applied_rate int,
@mdc_code int,
@cal_month int,
@cal_year int,
@cal_activity int,
@scenario_id int,
@initiative_id int,
@previous_initiative_id int,
@volume int,
@rate int,
@metric_to_be_applied nvarchar( 32 ),
@change int
declare c cursor for
select
iif( metric_to_be_applied = 'Volume', change, null ) as applied_volume,
iif( metric_to_be_applied = 'Rate', change, null ) as applied_rate,
mdc_code, cal_month, cal_year, activity, scenario_id, initiative_id, metric_to_be_applied, change
from
myp_initiatives
order by
initiative_id;
open c
while ( 1 = 1 )
begin
fetch next from c into
@applied_volume,
@applied_rate,
@mdc_code,
@cal_month,
@cal_year,
@cal_activity,
@scenario_id,
@initiative_id,
@metric_to_be_applied,
@change
if ( @@fetch_status != 0 ) break
if ( @previous_initiative_id is null )
begin
insert @t select
@mdc_code, @cal_month, @cal_year, @cal_activity, @scenario_id,
@initiative_id, @volume, @rate, @metric_to_be_applied, @change,
x.volume + @applied_volume as New_Volume_VolumeChange ,
x.rate * @applied_volume as New_Rate_VolumeChange,
(x.volume + @applied_volume)/x.rate as New_DemandHours_VolumeChange,
((x.volume + @applied_volume)/x.rate)/176 as New_DemandFTE_VolumeChange,
x.volume + @applied_rate as New_Volume_RateChange ,
x.rate * @applied_rate as New_Rate_RateChange,
(x.volume)/(x.rate + @applied_rate) as New_DemandHours_RateChange,
((x.volume)/(x.rate+ @applied_rate))/176 as New_DemandFTE_RateChange
from
myp_activity x
where
x.mdc_code = @mdc_code
and x.cal_month = @cal_month
and x.cal_year = @cal_year
and x.activity = @cal_activity
select @previous_initiative_id = @initiative_id
end
else
begin
insert @t select
@mdc_code, @cal_month, @cal_year, @cal_activity, @scenario_id,
@initiative_id, @volume, @rate, @metric_to_be_applied, @change,
New_Volume_VolumeChange + @applied_volume as New_Volume_VolumeChange ,
New_Rate_VolumeChange * @applied_volume as New_Rate_VolumeChange,
(New_Volume_VolumeChange + @applied_volume)/New_Rate_VolumeChange as New_DemandHours_VolumeChange,
((New_Volume_VolumeChange + @applied_volume)/New_Rate_VolumeChange)/176 as New_DemandFTE_VolumeChange,
New_Volume_VolumeChange + @applied_rate as New_Volume_RateChange ,
New_Rate_VolumeChange * @applied_rate as New_Rate_RateChange,
(New_Volume_VolumeChange)/(New_Rate_VolumeChange + @applied_rate) as New_DemandHours_RateChange,
((New_Volume_VolumeChange)/(New_Rate_VolumeChange+ @applied_rate))/176 as New_DemandFTE_RateChange
from
@t x
where
x.mdc_code = @mdc_code
and x.cal_month = @cal_month
and x.cal_year = @cal_year
and x.cal_activity = @cal_activity
and x.initiative_id = @previous_initiative_id
select @previous_initiative_id = @initiative_id
end
end
return
end
Здесь происходит то, что функция начинается с записи первого набора значений в таблицу @t
, а затем вставляет обновленные значения, применяя результаты к каждой предыдущей инициативе и записывая их в @t
. В конце он возвращает таблицу.
Как только вы определили эту функцию, вы можете просто сказать:
select
* --> note: would be better to list columns...but I'm being lazy for clarity
from
AppliedInitiatives()
Если бы кто-то мог переписать это как cte, для меня это тоже был бы опыт обучения!