Оптимизировать хранимую процедуру - PullRequest
0 голосов
/ 19 июня 2019

У меня есть хранимая процедура, которая вызывается несколько раз, чтобы получить все элементы, необходимые для отображения страницы.

Пример данных:

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, равным нулю).

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 = ноль и @ 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

Тогда для получения parentIds потребуется 432 и 433;и затем он вызовет хранимую процедуру для выполнения с родительскими идентификаторами, оставив идентификатор плана нулевым.Например, при 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 являются параметрами хранимой процедуры, а результаты - после объединения нескольких таблиц и фильтрации с требуемыми условиями.

Может кто-нибудь помочь мне оптимизировать это, чтобы сделать хранимую процедуру с одним вызовом эффективной?

1 Ответ

1 голос
/ 19 июня 2019

Похоже на простое рекурсивное общее табличное выражение (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;
...