我这里有一个复杂的场景:
我有以下查询,该查询使我对表中指定的卷具有某种主动性。如果音量为1000,而更改为-500,则新音量为500。速率相同。这是更新新数量,新费率,新需求小时数和新需求FTE的查询。
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,
CASE WHEN y.metric_to_be_applied = 'Volume'
THEN x.volume + y.change end as New_Volume_VolumeChange ,
CASE WHEN y.metric_to_be_applied = 'Volume'
THEN x.rate end as New_Rate_VolumeChange,
CASE WHEN y.metric_to_be_applied = 'Volume'
THEN (x.volume + y.change)/x.rate end as New_DemandHours_VolumeChange,
CASE WHEN y.metric_to_be_applied = 'Volume'
THEN ((x.volume + y.change)/x.rate)/176 end as New_DemandFTE_VolumeChange,
CASE WHEN y.metric_to_be_applied = 'Rate'
THEN x.volume end as New_Volume_RateChange ,
CASE WHEN y.metric_to_be_applied = 'Rate'
THEN x.rate + y.change end as New_Rate_RateChange,
CASE WHEN y.metric_to_be_applied = 'Rate'
THEN (x.volume)/(x.rate + y.change) end as New_DemandHours_RateChange,
CASE WHEN y.metric_to_be_applied = 'Rate'
THEN ((x.volume)/(x.rate+ y.change))/176 end as New_DemandFTE_RateChange
from
(SELECT [id] as activity_id
,[mdc_code]
,[function_name]
,[cal_month]
,[cal_year]
,[model_type]
,[activity]
,[activity_type]
,[product_category]
,[project_category]
,[segment]
,[volume]
,[demand_fte]
,[demand_hours]
,[rate]
,[sub_division_name]
,[division_name]
,[myp_year]
,[client_count]
,[calls]
,[loguser]
,[logdate]
,[IsProd]
,[version_id]
FROM [myp_activity]
)x
join
(
SELECT [id]
,[scenario_id]
,[initiative_id]
,[initiative_name]
,[comments]
,[recommended_by]
,[mdc_code]
,[function_name]
,[cal_month]
,[cal_year]
,[model_type]
,[activity]
,[metric_to_be_applied]
,[change_type]
,[change]
,[sub_division_name]
,[division_name]
,[myp_year]
,[loguser]
,[logdate]
,[IsProd]
,[version_id]
,[initiative_type]
FROM [myp_initiatives] where initiative_id=10001
) 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
此查询的输出如下:
还有4个未在图片中列出的列(New_Volume_RateChange,New_Rate_RateChange,New_DemandHours_RateChange,New_DemandFTE_RateChange)。
我需要对此数据应用主动10002。计划10002的详细信息显示在计划表中,该表已用于加入。现在,输出已对其应用了主动权10001。 例如: 如果Initiative 10001在其中一个行中将Volume列为500,而Initiative 2更改为-300,则该行中的Volume列应具有200作为输出。 另外,由于主动10002是最后应用的主动,所以Initiative_id应该从10001更改为10002。
同样,如果我们列出了要在倡议10002上应用的倡议10003,那么输出应列出10003作为倡议。
因此,应该对从上述查询生成的数据应用“主动性10002”,“ 10003”等。
在所有这些情况下,两个表(启动和活动)的连接条件将与查询中列出的条件相同。
我该如何实现?
我尝试过CTE,但无法做到。我对如何执行计算(CASE WHEN语句)感到困惑。
答案 0 :(得分:1)
编辑
这几乎完全重写了我以前的答案
仍然,如前所述,我将失去所有括号...它们只会使您的代码更加不可读。当列名与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,那对我来说也是一种学习经历!
答案 1 :(得分:0)
尽管您可能会或可能不会获得包括修改后的代码版本的答案,但是您可能希望查看下面的简化查询,以了解解决您的“运行值”问题的一种方法。
DECLARE @Initiative TABLE (IntiativeID INT, AddToValue INT, Code NVARCHAR(10))
DECLARE @Data TABLE(DataID INT, Value INT, Code NVARCHAR(10))
INSERT @Data VALUES(1,10,'A'),(2,10,'B'),(3,10,'A')
INSERT @Initiative VALUES(1,5,'A'),(2,5,'A'),(4,5,'B'),(800,5,'C'),(24,5,'D')
SELECT
DataId,
StartValue = Value,
LastIntiativeID = MAX(IntiativeID),
EndValue = Value + SUM(AddToValue)
FROM
@Data D
LEFT JOIN @Initiative I ON D.Code = I.Code
GROUP BY
DataID,Value
ORDER BY
DataID