将编号类别转换为命名类别
Convert numbered categories to named categories
我相信一定有一个简单的解决方案。我有两个 tables,一个是库存数据,另一个是保存项目类别名称的地方。
那么让我们想象一下股票 table
ID | Name | Price | CategoryID
_____________________________________________
5465814 |Item1 | 2.00 | 1
5465815 |Item2 | 2.00 | 2
5465816 |Item3 | 2.00 | 1/1
5465817 |Item4 | 2.00 | 1/3/5
5465818 |Item5 | 2.00 | 4
5465818 |Item5 | 2.00 | 4/1
5465818 |Item5 | 2.00 | 4/2/7
那么类别 table 是这样的:
CategoryID| Name
_____________________________________________
1 |Tools
1/1 |Manual
1/2 |Electrical
1/3 |Pneumatic
1/3/5 |Saws
2 |Chairs
4 |Toys
4/1 |for Girls
4/1/1 |Dolls
4/2 |for Boys
4/2/1 |Cars
4/2/7 |Action Figures
我想不通的是如何在将此 ID 加入 select 时转换为组合类别名称,例如将 4/2/7 转换为:
Toys > for Boys > Action Figures
我最终想要完成的是得到一个像这样的 table:
ID | Name | Price | Category
_____________________________________________
5465814 |Item1 | 2.00 | Tools
5465815 |Item2 | 2.00 | Chairs
5465816 |Item3 | 2.00 | Tools > Manual
5465817 |Item4 | 2.00 | Tools > Pneumatic > Saws
5465818 |Item5 | 2.00 | Toys
5465818 |Item5 | 2.00 | Toys > for Girls
5465818 |Item5 | 2.00 | Toys > for Boys > Action Figures
这是我目前得到的结果,它最多可以使用 4 个嵌套类别名称:
CASE
WHEN len(sd.CategoriyID) - len(replace(sd.CategoriyID,'/','')) = 0
THEN ISNULL((SELECT Name FROM Categories WHERE ID = sd.CategoriyID), '')
WHEN len(sd.CategoriyID) - len(replace(sd.CategoriyID,'/','')) = 1
THEN
ISNULL((SELECT Name FROM Categories WHERE ID =
SUBSTRING(sd.CategoriyID, 1 , dbo.CHARINDEX2('/', sd.CategoriyID, 1) - 1)), '')
+ ' > '
+ ISNULL((SELECT Name FROM Categories WHERE ID = sd.CategoriyID), '')
WHEN len(sd.CategoriyID) - len(replace(sd.CategoriyID,'/','')) = 2
THEN
ISNULL((SELECT Name FROM Categories WHERE ID =
SUBSTRING(sd.CategoriyID, 1 , dbo.CHARINDEX2('/', sd.CategoriyID, 2) - 1)), '')
+ ' > '
+ISNULL((SELECT Name FROM Categories WHERE ID =
SUBSTRING(sd.CategoriyID, 1 , dbo.CHARINDEX2('/', sd.CategoriyID, 1) - 1)), '')
+ ' > '
+ ISNULL((SELECT Name FROM Categories WHERE ID = sd.CategoriyID), '')
WHEN len(sd.CategoriyID) - len(replace(sd.CategoriyID,'/','')) = 2
THEN
ISNULL((SELECT Name FROM Categories WHERE ID =
SUBSTRING(sd.CategoriyID, 1 , dbo.CHARINDEX2('/', sd.CategoriyID, 3) - 1)), '')
+ ' > '
+ISNULL((SELECT Name FROM Categories WHERE ID =
SUBSTRING(sd.CategoriyID, 1 , dbo.CHARINDEX2('/', sd.CategoriyID, 2) - 1)), '')
+ ' > '
+ISNULL((SELECT Name FROM Categories WHERE ID =
SUBSTRING(sd.CategoriyID, 1 , dbo.CHARINDEX2('/', sd.CategoriyID, 1) - 1)), '')
+ ' > '
+ ISNULL((SELECT Name FROM Categories WHERE ID = sd.CategoriyID), '')
END AS Category
SQL 服务器不支持将字符串 agg 作为 window 函数用于累积 windows。但是,您可以改用 apply
。因此,使用以下方法从第二个 table 获取全名:
select c.*, v.category
from category c cross apply
(values (stuff( (select ' > ' + coalesce(c2.name, '')
from category c2
where c.categoryId + '/' like c2.categoryId + '/%'
order by c2.categoryId
for xml path (''), type) .value('.', 'nvarchar(max)'
), 1, 3, ''
)
)
) v(category);
Here 是这部分的 db<>fiddle。
然后您可以 join
此查询:
with c as (
select c.*, v.category
from category c cross apply
(values (stuff( (select ' > ' + coalesce(c2.name, '')
from category c2
where c.categoryId + '/' like c2.categoryId + '/%'
order by c2.categoryId
for xml path (''), type) .value('.', 'nvarchar(max)'
), 1, 3, ''
)
)
) v(category);
)
select s.*, c.category
from stock s join
c
on s.categoryId = c.categoryId;
我相信一定有一个简单的解决方案。我有两个 tables,一个是库存数据,另一个是保存项目类别名称的地方。 那么让我们想象一下股票 table
ID | Name | Price | CategoryID
_____________________________________________
5465814 |Item1 | 2.00 | 1
5465815 |Item2 | 2.00 | 2
5465816 |Item3 | 2.00 | 1/1
5465817 |Item4 | 2.00 | 1/3/5
5465818 |Item5 | 2.00 | 4
5465818 |Item5 | 2.00 | 4/1
5465818 |Item5 | 2.00 | 4/2/7
那么类别 table 是这样的:
CategoryID| Name
_____________________________________________
1 |Tools
1/1 |Manual
1/2 |Electrical
1/3 |Pneumatic
1/3/5 |Saws
2 |Chairs
4 |Toys
4/1 |for Girls
4/1/1 |Dolls
4/2 |for Boys
4/2/1 |Cars
4/2/7 |Action Figures
我想不通的是如何在将此 ID 加入 select 时转换为组合类别名称,例如将 4/2/7 转换为:
Toys > for Boys > Action Figures
我最终想要完成的是得到一个像这样的 table:
ID | Name | Price | Category
_____________________________________________
5465814 |Item1 | 2.00 | Tools
5465815 |Item2 | 2.00 | Chairs
5465816 |Item3 | 2.00 | Tools > Manual
5465817 |Item4 | 2.00 | Tools > Pneumatic > Saws
5465818 |Item5 | 2.00 | Toys
5465818 |Item5 | 2.00 | Toys > for Girls
5465818 |Item5 | 2.00 | Toys > for Boys > Action Figures
这是我目前得到的结果,它最多可以使用 4 个嵌套类别名称:
CASE
WHEN len(sd.CategoriyID) - len(replace(sd.CategoriyID,'/','')) = 0
THEN ISNULL((SELECT Name FROM Categories WHERE ID = sd.CategoriyID), '')
WHEN len(sd.CategoriyID) - len(replace(sd.CategoriyID,'/','')) = 1
THEN
ISNULL((SELECT Name FROM Categories WHERE ID =
SUBSTRING(sd.CategoriyID, 1 , dbo.CHARINDEX2('/', sd.CategoriyID, 1) - 1)), '')
+ ' > '
+ ISNULL((SELECT Name FROM Categories WHERE ID = sd.CategoriyID), '')
WHEN len(sd.CategoriyID) - len(replace(sd.CategoriyID,'/','')) = 2
THEN
ISNULL((SELECT Name FROM Categories WHERE ID =
SUBSTRING(sd.CategoriyID, 1 , dbo.CHARINDEX2('/', sd.CategoriyID, 2) - 1)), '')
+ ' > '
+ISNULL((SELECT Name FROM Categories WHERE ID =
SUBSTRING(sd.CategoriyID, 1 , dbo.CHARINDEX2('/', sd.CategoriyID, 1) - 1)), '')
+ ' > '
+ ISNULL((SELECT Name FROM Categories WHERE ID = sd.CategoriyID), '')
WHEN len(sd.CategoriyID) - len(replace(sd.CategoriyID,'/','')) = 2
THEN
ISNULL((SELECT Name FROM Categories WHERE ID =
SUBSTRING(sd.CategoriyID, 1 , dbo.CHARINDEX2('/', sd.CategoriyID, 3) - 1)), '')
+ ' > '
+ISNULL((SELECT Name FROM Categories WHERE ID =
SUBSTRING(sd.CategoriyID, 1 , dbo.CHARINDEX2('/', sd.CategoriyID, 2) - 1)), '')
+ ' > '
+ISNULL((SELECT Name FROM Categories WHERE ID =
SUBSTRING(sd.CategoriyID, 1 , dbo.CHARINDEX2('/', sd.CategoriyID, 1) - 1)), '')
+ ' > '
+ ISNULL((SELECT Name FROM Categories WHERE ID = sd.CategoriyID), '')
END AS Category
SQL 服务器不支持将字符串 agg 作为 window 函数用于累积 windows。但是,您可以改用 apply
。因此,使用以下方法从第二个 table 获取全名:
select c.*, v.category
from category c cross apply
(values (stuff( (select ' > ' + coalesce(c2.name, '')
from category c2
where c.categoryId + '/' like c2.categoryId + '/%'
order by c2.categoryId
for xml path (''), type) .value('.', 'nvarchar(max)'
), 1, 3, ''
)
)
) v(category);
Here 是这部分的 db<>fiddle。
然后您可以 join
此查询:
with c as (
select c.*, v.category
from category c cross apply
(values (stuff( (select ' > ' + coalesce(c2.name, '')
from category c2
where c.categoryId + '/' like c2.categoryId + '/%'
order by c2.categoryId
for xml path (''), type) .value('.', 'nvarchar(max)'
), 1, 3, ''
)
)
) v(category);
)
select s.*, c.category
from stock s join
c
on s.categoryId = c.categoryId;