我有一个存储过程,该过程被多次调用以获取显示页面所需的所有元素。
样本数据:
CREATE TABLE #temp
(plan_id INT, parentid INT, label VARCHAR(20), color VARCHAR(10), comp_id INT, start_date DATETIME)
INSERT INTO #temp
VALUES
(607, NULL,'abc', 'CDC', 432, '2018-05-22 00:00:00'),
(607,NULL,'abc', 'CDC', 432, '2018-05-22 00:00:00'),
(607,NULL,'abc', 'CDC', 433, '2018-05-22 00:00:00'),
(NULL,432,'def', 'CDC', 434, '2018-05-22 00:00:00'),
(NULL,432,'def', 'CDC', 434, '2018-05-22 00:00:00'),
(NULL,433,'def', 'CDC', 435, NULL),
(NULL,433,'def', 'CDC', 435, NULL),
(NULL,434,'obj', 'CDC', 436, '2018-05-22 00:00:00'),
(NULL,434,'obj', 'CDC', 436, '2018-05-22 00:00:00'),
(NULL,435,'obj', 'CDC', 437, NULL),
(NULL,436,'ion', 'CDC', 438, '2018-05-22 00:00:00'),
(NULL,436,'ion', 'CDC', 438, '2018-05-22 00:00:00'),
(NULL,437,'ion', 'CDC', 439, NULL)
存储过程的第一次调用提供一个plan_id(@plan_id)并获取父节点。然后,这些节点在页面代码中循环访问,并随后调用相同的存储过程,但循环中具有元素的comp_id,然后循环中的该元素与另一个调用一起循环以找到其子代。
在具有许多要素的大型计划中,这是非常低效的。 (例如,如果使用@plan_id = 607执行此操作,则将使用comp_id提取父节点;并且在下一个调用中将提供它们,而@plan_id为null)。
DECLARE
@plan_id INT =null,
@parentid INT =null
IF @plan_id is not null
BEGIN
SELECT label, color, comp_id, start_date FROM #temp WHERE plan_id = @plan_id
END
ELSE
BEGIN
SELECT label, color, comp_id, start_date FROM #temp WHERE parentid = @parentid
END
即将使用@plan_id = 607和@parentid = null来调用存储过程。 @plan_id = null和@ 432; @plan_id = null和@parentid = 433; @plan_id = null和@parentid = 434; @plan_id = null和@parentid = 435; @plan_id = null和@parentid = 436;和@plan_id = null和@parentid = 437
例如:当@plan_id = 607时,输出为:
我想要做的是,在一个有效的存储过程中构建它,该过程将返回显示页面所需的所有内容。
根据我们的示例,我希望得到如下结果:
SELECT label, color, comp_id, start_date FROM #temp
它第一次以plan_id = 607执行时,存储过程给出:
label color comp_id start_date
abc CDC 432 2018-05-22 00:00:00.000
abc CDC 432 2018-05-22 00:00:00.000
abc CDC 433 2018-05-22 00:00:00.000
然后,将需要432和433来获取parentIds;然后它将使用父ID调用存储过程来执行,并保持计划ID为空。例如,对于parentid = 432,它将返回以下输出:
label color comp_id start_date
def CDC 434 2018-05-22 00:00:00.000
def CDC 434 2018-05-22 00:00:00.000
该表仅是显示其工作方式和预期输出的示例。
否则,plan_id和parentid是存储过程的参数,结果是在联接多个表并按所需条件进行过滤之后得出的。
任何人都可以帮助我优化此过程,以使单个调用高效地存储过程吗?
答案 0 :(得分:1)
它看起来像一个简单的递归公用表表达式(CTE):
declare @Samples as Table ( PlanId Int, ParentId Int, Label VarChar(20), Color VarChar(10), CompId Int, StartDate DateTime );
insert into @Samples ( PlanId, ParentId, Label, Color, CompId, StartDate ) values
(607, NULL,'abc', 'CDC', 432, '2019-05-22 00:00:00'),
(607,NULL,'abc', 'CDC', 432, '2018-05-22 00:00:00'),
(607,NULL,'abc', 'CDC', 433, '2018-05-22 00:00:00'),
(NULL,432,'def', 'CDC', 434, '2018-05-22 00:00:00'),
(NULL,432,'def', 'CDC', 434, '2018-05-22 00:00:00'),
(NULL,433,'def', 'CDC', 435, NULL),
(NULL,433,'def', 'CDC', 435, NULL),
(NULL,434,'obj', 'CDC', 436, '2018-05-22 00:00:00'),
(NULL,434,'obj', 'CDC', 436, '2018-05-22 00:00:00'),
(NULL,435,'obj', 'CDC', 437, NULL),
(NULL,436,'ion', 'CDC', 438, '2018-05-22 00:00:00'),
(NULL,436,'ion', 'CDC', 438, '2018-05-22 00:00:00'),
(NULL,437,'ion', 'CDC', 439, NULL);
select * from @Samples;
with Things as (
-- Get all of the plans ...
select PlanId, ParentId, Label, Color, CompId, StartDate
from @Samples
where ParentId is NULL
union all
-- ... add the children one level at a time.
select S.PlanId, S.ParentId, S.Label, S.Color, S.CompId, S.StartDate
from Things as T inner join @Samples as S on T.CompId = S.ParentId
)
select PlanId, ParentId, Label, Color, CompId, StartDate
from Things;