如何在执行计算时迭代SQL中的值?
我这里有一个比较复杂的场景: 我有一个查询,它告诉我某个计划对表中指定的卷的影响。如果卷为1000,更改为-500,则新卷为500。同样的逻辑也适用于利率。以下是更新新数量、新费率、新需求工时和新需求FTE的查询如何在执行计算时迭代SQL中的值?,sql,sql-server,recursion,common-table-expression,Sql,Sql Server,Recursion,Common Table Expression,我这里有一个比较复杂的场景: 我有一个查询,它告诉我某个计划对表中指定的卷的影响。如果卷为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,
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列未在图片中列出(新数量、新费率、新需求时费率、新需求时费率)
我需要对这些数据应用倡议10002。计划10002的详细信息见已用于加入的计划表。现在输出已经应用了主动10001。
例如:
如果计划10001的某一行中列出的卷为500,而计划2的更改为-300,则输出应该有200作为该特定行中列出的卷列。
此外,方案id应从10001更改为10002,因为方案10002是最后应用的方案
同样,如果我们列出了将应用于方案10002的方案10003,那么输出应将10003列为方案
因此,应将计划10002、10003等应用于从上述查询生成的我的数据
在所有这些情况下,两个表(主动性和活动)的联接条件都将与查询中列出的相同
我如何做到这一点
我试过CTE,但做不到。我不知道如何对其执行计算(CASE-WHEN语句)。虽然您可能会或可能不会得到包含代码修改版本的答案,但您可能希望查看下面的简化查询,以了解解决“运行值”问题的一种方法
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
编辑
这几乎是对我以前的答案的完全重写
不过,正如前面提到的,我会丢失所有的括号…它们只会让你的代码更不可读。实际上,只有当列名与SQL中的保留字冲突时,才需要它们
接下来,您不必从select
到alias中select
,也不必担心在中间结果中获得额外数据。在进行某种聚合或计算时,实际上应该只从select
中选择。一个很好的例子是你的y
…在这里你可以计算计算的基本因子…然后完全摆脱案例
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
,我确信这是不对的。您必须编辑数据类型以匹配您真正拥有的数据类型
这里发生的事情是,函数首先将第一组值写入表@t
,然后将结果应用到每个先前的倡议并将其写入@t
,插入更新的值。最后,它返回表
定义此函数后,您可以说:
select
* --> note: would be better to list columns...but I'm being lazy for clarity
from
AppliedInitiatives()
如果有人能把它改写成cte,对我来说也是一次学习的经历 我能理解你的一系列计划吗?也就是说,在10001和10002的结果中加入10001和10002,然后在10001和10002的结果中加入10003?是否有固定数量的计划…或者有很多计划?以及…是否所有的中间结果都要显示?还是我们只对最终的应用计划感兴趣?这是一个很好的开始,我不需要显示中间结果。是的,10002应用于10001,给我一个新的数据集,10003将应用于该数据集。我得到以下错误:“Msg 240,16级,状态1,行1类型在递归查询“base”的“mdc_代码”列中的锚和递归部分之间不匹配”。“知道我哪里出错了吗?是的……我在第二部分输入了错误。”(递归部分)…应该是x.mdc\u代码、x.cal\u月、x.cal\u年、x.activity选择列表…已修复it@AsheshDas我更新了代码…让我知道你是如何处理它的。嗨,克莱,当我为initiative_id=10002执行这个CTE时,行数从336增加到2688。知道为什么会发生这种情况吗?还有当initiative 10002应用时的新卷应该是=(initiative 10001的新卷)+(change in 10002),输出中显示的initiative_id应该是10002。我如何合并它?在更改数据类型并执行函数后,我得到了一个“Divide by zero error Incometed.”错误。我知道如何避免这个错误吗?
select
* --> note: would be better to list columns...but I'm being lazy for clarity
from
AppliedInitiatives()