2013-07-12 75 views
0

我有一個結點表,它包含項目之間的相關性。我正在使用它以編程方式創建顯示這些依賴關係的甘特圖。我現在有一個可用的存儲過程,但是我的公司的政策是儘可能避免遊標。我把它放在那裏,你可以在沒有光標的情況下做到這一點嗎? DATA: 我可以不使用此遊標嗎

 
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

存儲過程的代碼:

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起,您可以使用表值構造函數替代union all來填充表 - http:// technet。 magic!microsoft.com/en-us/library/dd776382.aspx – gotqn

回答

2

一般來說,許多光標T-SQL語句可以改寫使用遞歸公用表表達式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

魔法!謝謝gotqn。關於你最後一點的說明,因爲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 
相關問題