我需要根据其他计算进行计算。这些计算与会计代码相关联,因此我需要按计算优先顺序对代码进行排序。想一想:如果x = .1(y)和y = .30(z),并且z = 1 + 2 + 3那么我需要计算z然后是y,最后是x。
下面的示例数据将我的Xs,Ys和Zs表示为我需要计算的会计代码 对于每一行,我知道必须在第二个字段之前计算第一个字段。我需要完成的是按计算优先顺序获取所有代码。
以下是我为解决此问题而开发的代码。我打开这个问题希望有一个更清洁/更好的解决方案。
DECLARE @tbAccCodes TABLE (acct_code varchar(50), process_order int NULL)
INSERT INTO @tbAccCodes
VALUES
('195',NULL),
('220',NULL),
('225',NULL),
('301',NULL),
('304',NULL),
('620',NULL),
('500',NULL),
('510',NULL)
DECLARE @tbCodeDependency TABLE (calc_b4 varchar(50), this varchar(50))
INSERT INTO @tbCodeDependency
VALUES
('195','500'),
('195','510'),
('220','500'),
('220','510'),
('225','220'),
('225','500'),
('225','510'),
('301','500'),
('301','510'),
('304','500'),
('304','510'),
('620','800')
--------------------------------------------------------------------------------
-- Order acct_code codes by calculation precedence
----------------------------------------------------------------------------------
DECLARE @left_acct_code varchar(50), @right_acct_code varchar(50), @left_process_order int, @right_process_order int
DECLARE curCalcPrecedence CURSOR FOR
SELECT * FROM @tbCodeDependency
--The actual sorting by calculation precedence is done here
OPEN curCalcPrecedence
FETCH NEXT FROM curCalcPrecedence INTO @left_acct_code, @right_acct_code --- left acct_code depends on right acct_code so left needs to be calculated b4 right
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @left_process_order = process_order FROM @tbAccCodes WHERE acct_code = @left_acct_code
SELECT @right_process_order = process_order FROM @tbAccCodes WHERE acct_code = @right_acct_code
IF (@left_process_order < @right_process_order)
BEGIN
GOTO Cont -- the order is already correct. Go to the next record
END
-- both process_order are null so update both to be at the end. Left first then right
IF(@left_process_order IS NULL AND @right_process_order IS NULL)
BEGIN
SELECT @left_process_order = MAX(ISNULL(process_order,0)) + 1 FROM @tbAccCodes
UPDATE @tbAccCodes SET process_order = @left_process_order WHERE acct_code = @left_acct_code
UPDATE @tbAccCodes SET process_order = @left_process_order + 1 WHERE acct_code = @right_acct_code
GOTO Cont
END
IF(@left_process_order IS NOT NULL AND @right_process_order IS NOT NULL)
BEGIN
-- they are in the wrong order because I already took care of both being not null in the correct order in the first check
UPDATE @tbAccCodes SET process_order = process_order -1 WHERE process_order < @right_process_order
UPDATE @tbAccCodes SET process_order = @right_process_order -1 WHERE acct_code = @left_acct_code
GOTO Cont
END
--left process_order is not null and right is null: update right to be at the end
IF(@left_process_order IS NOT NULL AND @right_process_order IS NULL)
BEGIN
UPDATE @tbAccCodes SET process_order = (SELECT MAX(process_order) FROM @tbAccCodes) + 1 WHERE acct_code = @right_acct_code
GOTO Cont
END
--last case left is null, right is not null: update left process order to be before right process order
IF(@left_process_order IS NULL AND @right_process_order IS NOT NULL)
BEGIN
UPDATE @tbAccCodes SET process_order = process_order +1 WHERE process_order > @right_process_order -1 -- NOTE: > @right_process_order -1 is more efficient than >=right_process_order
UPDATE @tbAccCodes SET process_order = @right_process_order WHERE acct_code = @left_acct_code
GOTO Cont
END
Cont:
------------------------------------------------------------------------------------------------------------------------
--test line to see each iteration
--select * from @tbAccCodes ORDER BY process_order
--end test
------------------------------------------------------------------------------------------------------------------------
FETCH NEXT FROM curCalcPrecedence INTO @left_acct_code, @right_acct_code
END
CLOSE curCalcPrecedence
DEALLOCATE curCalcPrecedence
SELECT * FROM @tbAccCodes ORDER BY process_order
数据集是动态的,不允许循环引用。
如果这样可以更好地理解这个问题,那么我最初的要求就是:
允许最终用户输入%值和代码列表来计算代码。所以 代码240 =(用户输入%)的值(用户输入的代码列表)的总和 代码301 =(用户输入的%)(用户输入的代码列表)值的总和 代码195 =(用户输入的%)(用户输入的代码列表)值的总和 ......
此外,“用户输入的代码列表”可以是单个代码,由逗号分隔的代码,代码范围以及要从包含的范围中排除的代码和代码范围。
示例:代码240 =代码值301,304,200-299.99,-220,-260-270的总和的10%
使用逗号分割上面的内容,它会显示:
添加310
添加304
添加200到299.99之间的所有代码
删除代码220
删除260到270之间的所有代码。
所有这一切只需240.计算240中包含的所有代码都需要在240之前计算。
然后让我们说195 = 5%的240
现在,需要在195之前计算240。
对于长篇文章感到抱歉,但由于ppl错误地认为代码是实际数字,我原来简洁的文字引起了混乱。
由于
答案 0 :(得分:0)
假设我对多米诺骨牌/菊花链场景是正确的,看看这是否适合您。请注意,我的空白字符串为#34;空白&#34;如果您有空格或空值,则需要相应地修改脚本。
DECLARE @codes TABLE (dependant varchar(50), dependancy varchar(50))
INSERT INTO @codes
VALUES
('','195'),
('195','304'),
('225','290'),
('304','220'),
('301','225'),
('220','301'),
('290','')
;with r_cte (code)
as (select dependant from @codes where dependancy = ''
union all
select dependant
from @codes c
inner join r_cte r
on r.code = c.dependancy
where c.dependant <> '')
select * from r_cte