从存储过程输出将字符串整理到树中

时间:2014-08-05 08:02:55

标签: sql sql-server stored-procedures

我有一个复杂的存储过程MyStoredProc(我无法更改,这个例子大大简化了),它获取了一个Id并返回了一个ID和标题列表,类似于:

输入= 100

Id     Title      HasChilds
----------------------------
101    CategoryA  0
102    CategoryB  0
103    CategoryC  1
104    CategoryD  0

输入= 103

Id     Title      HasChilds
----------------------------
105    SubCatA    0
106    SubCatB    1
107    SubCatC    0

输入= 106

Id     Title      HasChilds
----------------------------
108    SubA       0
109    SubB       0

我的目标是编写一个查询来将其整理成一行,并将分支放在括号中:

CategoryA, CategoryB, CategoryC (SubCatA, SubCatB (SubA, SubB), SubCatC), CategoryD

鉴于深度不超过4-5级,我该如何在T-SQL中执行此操作?

我尝试将MyStoredProc输出转储到临时表

INSERT INTO #tmpTable 
  EXEC MyStoredProc @_Id = 100

然后用光标遍历它并将分支附加到同一个临时表。那就是我被困住的地方。我不知道如何将ParentId附加到临时表行,以便我可以使用从最后一行的光标到第一个将分支字符串附加到父行字符串。也许这完全是错误的做法。

1 个答案:

答案 0 :(得分:1)

这应该这样做(注意这里的一半脚本是设置与你的例子匹配的数据):

CREATE PROCEDURE MyStoredProc (
    @Id INT)
AS
BEGIN
    IF @Id = 100
    BEGIN
        SELECT 101 AS Id, 'CategoryA' AS Title, 0 AS HasChilds
        UNION ALL
        SELECT 102 AS Id, 'CategoryB' AS Title, 0 AS HasChilds
        UNION ALL
        SELECT 103 AS Id, 'CategoryC' AS Title, 1 AS HasChilds
        UNION ALL
        SELECT 104 AS Id, 'CategoryD' AS Title, 0 AS HasChilds
    END;
    IF @Id = 103
    BEGIN
        SELECT 105 AS Id, 'SubCatA' AS Title, 0 AS HasChilds
        UNION ALL
        SELECT 106 AS Id, 'SubCatB' AS Title, 1 AS HasChilds
        UNION ALL
        SELECT 107 AS Id, 'SubCatC' AS Title, 0 AS HasChilds
    END;
    IF @Id = 106
    BEGIN
        SELECT 108 AS Id, 'SubA' AS Title, 0 AS HasChilds
        UNION ALL
        SELECT 109 AS Id, 'SubB' AS Title, 0 AS HasChilds
    END;
END;
GO
CREATE PROCEDURE GetCategoryList(
    @StartId INT,
    @Result VARCHAR(2048) OUTPUT)
AS
BEGIN
    DECLARE @tmpTable TABLE (
        Id INT,
        Title VARCHAR(50),
        HasChilds INT);
    INSERT INTO @tmpTable EXEC MyStoredProc @StartId;
    DECLARE @Id INT = NULL;
    SELECT TOP 1 @Id = Id FROM @tmpTable ORDER BY Id;
    SELECT @Result = '';
    WHILE @Id IS NOT NULL
    BEGIN
        DECLARE @Title VARCHAR(50);
        DECLARE @HasChilds INT;
        SELECT @Title = Title, @HasChilds = HasChilds FROM @tmpTable WHERE Id = @Id;
        SELECT @Result = @Result + @Title;
        IF @HasChilds = 0
        BEGIN
            SELECT @Result = @Result + ', ';
        END;
        ELSE
        BEGIN
            DECLARE @Append VARCHAR(2048);
            EXEC GetCategoryList @Id, @Append OUTPUT;
            SELECT @Result = @Result + ' (' + @Append + '), ';
        END;

        --Get the next id
        DECLARE @LastId INT;
        SELECT @LastId = @Id;
        SELECT @Id = NULL;
        SELECT TOP 1 @Id = Id FROM @tmpTable WHERE Id > @LastId ORDER BY Id;
    END;
    SELECT @Result = SUBSTRING(@Result, 1, LEN(@Result) - 1);
END;
GO
DECLARE @Result VARCHAR(2048);
EXEC GetCategoryList 100, @Result OUTPUT;
SELECT @Result;