SQL将路径列分解为分层数据

时间:2017-08-07 22:27:01

标签: sql sql-server

现有表格如下:

Categories
----------------------------------------------
Drinks\Soda
Drinks\Juice\Fruit Juice\Apple Juice\Sugar Free
Food\Fruit\Oranges
Food\Fruit\Apples\Golden
Food\Fruit\Apples\Red Delicious
Food\Vegetables\Potatoes
Food\Meat
Food

我需要将它处理成分层数据表,如下所示:

Id  | ParentId |  Category   | Full path
------------------------------------------
1   | null     | Drinks      | Drinks
2   | 1        | Soda        | Drinks\Soda
3   | 1        | Juice       | Drinks\Juice
4   | 3        | Fruit Juice | Drinks\Juice\Fruit Juice
5   | 4        | Apple Juice | Drinks\Juice\Fruit Juice\Apple Juice
6   | 5        | Sugar Free  | Drinks\Juice\Fruit Juice\Apple Juice\Sugar Free
7   | null     | Food        | Food
8   | 7        | Fruit       | Food\Fruit
9   | 8        | Oranges     | Food\Fruit\Oranges
10  | 8        | Apple       | Food\Fruit\Apples

我正在使用SQL Server 2012。

我以为我有一个交叉申请,但后来我为每个父母获得了多行,我最终得到了类似下表的内容,这不是我需要的:

Category   | Full path
------------------------------------------
Drinks      | Drinks\Soda
Soda        | Drinks\Soda
Drinks      | Drinks\Juice
Juice       | Drinks\Juice

编辑:这是我到目前为止所做的:

CREATE TABLE [dbo].[food_categories3](
    [id] [int] NOT NULL,
    [category] [varchar](350) NULL)

insert into food_categories3
values 
(1,'Drinks\Soda'),
(2,'Drinks\Juice\Fruit Juice\Apple Juice\Sugar Free'),
(3,'Food\Fruit\Oranges'),
(4,'Food\Fruit\Apples\Golden'),
(5,'Food\Fruit\Apples\Red Delicious'),
(6,'Food\Vegetables\Potatoes'),
(7, 'Food\Meat'),
(8,'Food')

select * from food_categories3

 SELECT distinct X.category,
     splitted.x.value('.', 'VARCHAR(100)') AS cat  
 FROM  (SELECT  category,  
         CAST ('<M>' + REPLACE(category, '\', '</M><M>') + '</M>' AS XML) AS cat  
     FROM  food_categories3) AS X CROSS APPLY cat.nodes ('/M') AS splitted(x) 
order by category

另外,我的实际数据集与果实类别无关,这只是我数据结构的一个简单示例。

编辑2:我现在的主要问题是,如何在插入孩子时跟踪父行,比如我怎么知道橘子和苹果都是“水果”的孩子。

1 个答案:

答案 0 :(得分:2)

这是一个如何做到这一点的想法,使用递归CTE对您的父子关系进行排序。

我已经开始使用您的查询作为源而不更改它(CTE_Source)。接下来的两个CTE是一些数据准备。

第一次CTE - 剥离找到的类别的所有内容以获取正确的路径并过滤不同的值。

第二次CTE - 使用先前创建的路径,现在我们可以分配ID(使用DENSE_RANK函数)并计算每行的级别(计算斜线数)

最后使用计算出的路径和级别列现在不应该太难以递归地找到每个类别的ParentID

    for f in *{$i}000.png

SQLFiddle DEMO