我有一个连接表,用于保存项之间的依赖关系。我使用它以编程方式创建一个显示这些依赖项的甘特图。我现在有一个工作存储过程,但我公司的政策是尽可能避免使用游标。我把它放在那里的大师那里,没有光标可以做到这一点吗?
数据:
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
STORED 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 :(得分: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语句后的输出:
注意:我注意到在你的最后一行中你可能有语法错误(因为我已经理解了逻辑):
无论如何,如果我误解了某些事情,我相信你已经有了这个想法。
答案 1 :(得分:1)
我没有测试过这个。我正在使用autoincrement列来遍历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