2013-07-12 2 views
0

У меня есть таблица соединений, которая содержит зависимости между элементами. Я использую это, чтобы программно создать диаграмму gantt, показывающую эти зависимости. Сейчас у меня есть работающая хранимая процедура, однако политика моей компании заключается в том, чтобы избежать возможных курсоров. Я положил это на гуру, можно ли это сделать без курсора? ДАННЫЕ: Могу ли я обойтись без этого курсора

 
declare @BaseTable Table 
(
    [IssueDependencyId] [bigint] IDENTITY(1,1) NOT NULL, 
    [IssueId] [bigint] NOT NULL, 
    [DependsOnIssueId] [bigint] NOT NULL 
)

INSERT INTO @BaseTable SELECT 48, 0 UNION ALL SELECT 49, 48 UNION ALL SELECT 50, 48 UNION ALL SELECT 51, 48 UNION ALL SELECT 55, 48 UNION ALL SELECT 56, 48 UNION ALL SELECT 52, 49 UNION ALL SELECT 52, 50 UNION ALL SELECT 52, 51 UNION ALL SELECT 53, 52 UNION ALL SELECT 57, 54 UNION ALL SELECT 54, 55 UNION ALL SELECT 57, 56

SELECT * FROM @BaseTable

ЗАПОМНЕННАЯ код PROC:

DECLARE @IssueId int, @DependsOnIssueId int, @StartPoint int, @EndPoint int 
SET @StartPoint = 0 
SET @EndPoint = 10 

DECLARE @ResultsTable TABLE (
IssueId int not null, 
DependsOnIssueId int not null, 
Start_Point int, 
End_Point int 
) 
Select IssueId, DependsOnIssueId 
INTO #tmp1 
FROM IssueDependency 
WHERE UpperLevelIssueId = 48 
ORDER BY DependsOnIssueId 

declare MyCursor Cursor for (Select IssueId, DependsOnIssueId from #tmp1); 

OPEN MyCursor 

FETCH NEXT FROM MyCursor 
INTO @IssueId, @DependsOnIssueId 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    --get parent position to set start 
    SELECT @StartPoint = ISNULL(End_Point, 0) 
      FROM @ResultsTable WHERE IssueId = @DependsOnIssueId 
    SET @EndPoint = @StartPoint + 10 

    INSERT INTO @ResultsTable VALUES 
      (@IssueId, @DependsOnIssueId, @StartPoint, @EndPoint) 

    FETCH NEXT FROM MyCursor 
    INTO @IssueId, @DependsOnIssueId 
END 

Close MyCursor 

DEALLOCATE MyCursor; 

SELECT IssueId, 
     MAX(start_point) max_start_point, 
     MAX(end_point) max_end_point 
INTO #MaxPoints 
from @ResultsTable 
GROUP BY IssueId 

SELECT r.IssueId,DependsOnIssueId, 
     max_start_point start_point, 
     max_end_point end_point 
FROM @ResultsTable r 
JOIN #MaxPoints m ON m.IssueId = r.IssueId 
ORDER BY r.IssueId 

результирующие данные

IssueId DependsOnIssueId Start_Point End_Point 
-------------------------------------------------------------------- 
    48   0    0    10 
    49   48    10    20 
    50   48    10   20 
    51   48    10   20 
    52   49    20   30 
    52   50    20   30 
    52   51    20   30 
    53   52    30   40 
    54   55    20   30 
    55   48    10   20 
    56   48    10   20 
    57   54    30   40 
    57   56    30   40 

Ваша помощь очень признателен !!

+0

Для избежания курсоров вместо применения вычислений или манипуляций по одной записи сделайте это для всех записей и выберите нужный – Nithesh

+0

С SQL Server 2008 вы можете использовать конструктор табличных значений пользователя вместо объединения всех для заполнения таблиц - http: // technet. microsoft.com/en-us/library/dd776382.aspx – gotqn

ответ

2

Вообще, многие из операторов курсора T-SQL может быть переписать с помощью рекурсивной Common Table Expressions Recursive CTE. Вы также можете найти некоторые статьи о том, как производительность лучше, если вы используете эту технику.

В вас случае (это полный рабочий пример), решение выглядит следующим образом:

SET NOCOUNT ON 
GO 

    DECLARE @DataSource TABLE 
    (
     [IssueDependencyId] BIGINT IDENTITY(1,1) NOT NULL, 
     [IssueId] BIGINT NOT NULL, 
     [DependsOnIssueId] BIGINT NOT NULL 
    ) 

    INSERT INTO @DataSource ([IssueId], [DependsOnIssueId]) 
    VALUES (48, 0) 
      ,(49, 48) 
      ,(50, 48) 
      ,(51, 48) 
      ,(55, 48) 
      ,(56, 48) 
      ,(52, 49) 
      ,(52, 50) 
      ,(52, 51) 
      ,(53, 52) 
      ,(57, 54) 
      ,(54, 55) 
      ,(57, 56) 

    ;WITH DataSource ([IssueId], [DependsOnIssueId], [Start_Point], [End_Point]) AS 
    (
     SELECT AnchorMebemr.[IssueId] 
       ,AnchorMebemr.[DependsOnIssueId] 
       ,0 
       ,10 
     FROM @DataSource AS AnchorMebemr 
     WHERE AnchorMebemr.[IssueId] = 48 
     UNION ALL 
     SELECT RecursiveMebemer.[IssueId] 
       ,RecursiveMebemer.[DependsOnIssueId] 
       ,DS.[End_Point] 
       ,DS.[End_Point] + 10 
     FROM @DataSource AS RecursiveMebemer 
     INNER JOIN DataSource DS 
      ON RecursiveMebemer.[DependsOnIssueId] = DS.[IssueId] 

    ) 
    SELECT DISTINCT DS.[IssueId] 
        ,DS.[DependsOnIssueId] 
        ,DS.[Start_Point] 
        ,DS.[End_Point] 
    FROM DataSource DS 
    ORDER BY DS.[IssueId] 
      ,DS.[DependsOnIssueId] 

SET NOCOUNT OFF 
GO 

На скриншоте ниже показывает результат после исполнения T-SQL заявления выше:

enter image description here

Примечание: Я заметил, что в последнем ряду вы можете иметь синтаксическую ошибку (как и я понимаю логику):

enter image description here

В любом случае, если я что-то не понял, я уверен, что у вас есть идея.

+0

Magic! Спасибо, ты получил. Что касается вашей последней заметки, потому что 57 также зависит от 54, я позиционирую в конечной точке последней зависимости. Спасибо за ваше тщательное рассмотрение :) – KiwiSunGoddess

1

Я не проверял это. Я использую столбец автоинкремента для прокрутки таблицы temp1. Вот он идет:

DECLARE @tmp1 table 
(
    _ID int identity (1,1) , -- will be used for looping 
    IssueId int not null, 
    DependsOnIssueId int not null 
) 

DECLARE @i as int 
DECLARE @max as int 

INSERT INTO @tmp1 (IssueId, DependsOnIssueId) 
Select IssueId, DependsOnIssueId 
FROM IssueDependency 
WHERE UpperLevelIssueId = 48 
ORDER BY DependsOnIssueId 

SELECT @i = 1, @max = MAX(_ID) FROM @tmp1 

WHILE @i <= @max 
BEGIN 
SELECT @IssueId = IssueId, @DependsOnIssueId = DependsOnIssueId 
FROM @tmp1 WHERE _ID = @i 
    --get parent position to set start 
    SELECT @StartPoint = ISNULL(End_Point, 0) 
     FROM @ResultsTable WHERE IssueId = @DependsOnIssueId 
    SET @EndPoint = @StartPoint + 10 

    INSERT INTO @ResultsTable VALUES 
     (@IssueId, @DependsOnIssueId, @StartPoint, @EndPoint) 

    SET @i = @i + 1 
END 
Смежные вопросы