0

我有一个联结表,其中包含项目之间的依赖关系。我正在使用它以编程方式创建显示这些依赖关系的甘特图。我现在有一个有效的存储过程,但是我公司的政策是尽可能避免使用游标。我把它交给了那里的大师,没有光标可以做到这一点吗?数据:

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

非常感谢您的帮助!!

4

2 回答 2

2

通常,可以使用递归公用表表达式递归 CTE重写许多游标 T-SQL 语句。您还可以搜索一些有关使用此技术时性能如何提高的文章。

在您的情况下(这是完整的工作示例),解决方案如下所示:

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 语句后的输出:

在此处输入图像描述

注意:我注意到在你的最后一行中你可能有语法错误(因为我已经理解了逻辑):

在此处输入图像描述

无论如何,如果我误解了什么,我相信你已经明白了。

于 2013-07-12T06:51:24.390 回答
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
于 2013-07-12T05:33:59.280 回答