递归CTE可能吗?

时间:2014-08-17 01:32:48

标签: sql-server tsql recursion common-table-expression

我的产品数据采用以下格式构建:

ProductID   OptionID    Lvl OptionDescription   SubOptionID SubOptionDescription
HPH 6   1   Model   10  Studio
HPH 6   1   Model   11  DJ
HPH 7   2   Device  12  Bluetooth
HPH 7   2   Device  13  Cable
HPH 7   2   Device  14  Remote

产品可能有多个级别。我需要遍历层次结构并生成以下输出 - 每个产品选项的描述:

Studio-Bluetooth
Studio-Cable
Studio-Remote
DJ-Bluetooth
DJ-Cable
DJ-Remote

我看过CTE,但这些例子往往包含相邻的列表(employeeID; managerID..etc),这些似乎不合适。

如何实现此输出?

感谢。

CREATE TABLE [dbo].[Products](
    [ProductID] [varchar](50) NULL,
    [OptionID] [int] NULL,
    [Lvl] [int] NULL,
    [OptionDescription] [varchar](50) NULL,
    [SubOptionID] [int] NULL,
    [SubOptionDescription] [varchar](50) NULL
) ON [PRIMARY]

insert into Products (ProductID, OptionID, Lvl, OptionDescription, SubOptionID,    SubOptionDescription) values ('HPH', 6, 1, 'Model', 10, 'Studio')
insert into Products (ProductID, OptionID, Lvl, OptionDescription, SubOptionID, SubOptionDescription) values ('HPH', 6, 1, 'Model', 11, 'DJ')
insert into Products (ProductID, OptionID, Lvl, OptionDescription, SubOptionID, SubOptionDescription) values ('HPH', 7, 2, 'Device', 12, 'Bluetooth')
insert into Products (ProductID, OptionID, Lvl, OptionDescription, SubOptionID, SubOptionDescription) values ('HPH', 7, 2, 'Device', 13, 'Cable')
insert into Products (ProductID, OptionID, Lvl, OptionDescription, SubOptionID, SubOptionDescription) values ('HPH', 7, 2, 'Device', 14, 'Remote')

1 个答案:

答案 0 :(得分:0)

with cte as (
    -- Root level
    select p.Lvl, cast(p.SubOptionDescription as varchar(max)) as [ProductOption]
    from @Products p where p.Lvl = 1
    union all
    -- Anchor part - cartesian here?
    select p.Lvl, c.ProductOption + '-' + p.SubOptionDescription
    from @Products p
        inner join cte c on c.Lvl = p.Lvl - 1
)
select c.ProductOption from cte c;

几个笔记。

现在您的示例答案意味着您需要创建笛卡尔积。我希望情况并非如此,因为行数会爆炸式增加。如果您的样本中存在其他不明显的连接条件,您可以将它们引入CTE的锚点部分。

您可能还希望仅返回叶子行。有几种方法可以做到这一点 - 实际数据中可能存在某些属性,或者rank()top (1) with ties的组合可以解决这个问题,尽管它不会特别有效。< / p>