如何在 CTE 的所有递归行上提取相关的“锚”值
Posted
技术标签:
【中文标题】如何在 CTE 的所有递归行上提取相关的“锚”值【英文标题】:How to pull a related 'anchor' value on all recursive rows of a CTE 【发布时间】:2021-06-24 14:35:41 【问题描述】:以以下网站为起点 (https://www.sqlservertutorial.net/sql-server-basics/sql-server-recursive-cte/) , 我做了一个 CTE 查询,如下所示:
WITH q (n, Part_Number, Job, Material) AS (
SELECT
0,
Material.Part_Number,
Material_Req.Job,
Material_Req.Material
FROM
Production.dbo.Material_Req
INNER JOIN PRODUCTION.dbo.Material ON Material_Req.Job = Material.Job
WHERE e.Job LIKE 'TEMPLATE%' AND e.Material IN ('PART1')
UNION ALL
SELECT
n + 1,
Material.Part_Number,
Material_Req.Job,
Material_Req.Material
FROM
Production.dbo.Material_Req
INNER JOIN PRODUCTION.dbo.Material ON Material_Req.Job = Material.Job
INNER JOIN q ON q.Material = Material.Material
WHERE Material.Job LIKE 'TEMPLATE%')
SELECT DISTINCT n, Job, Part_Number, Material FROM q WHERE Job LIKE 'TEMPLATE%'
ORDER BY n
生成的结果如下表所示,相对易于导航,尤其是在最终用户知道内容的情况下。
n | Job | Part_Number | Material |
---|---|---|---|
0 | TEMP1 | PART1 | PART1a |
0 | TEMP1 | PART1 | PART1b |
1 | TEMP2 | PART1a | MATERIAL1 |
1 | TEMP3 | PART1b | PART1b1 |
2 | TEMP4 | PART1b1 | PART1b1a |
3 | TEMP5 | PART1b1a | MATERIAL2 |
但是,如果我要在锚点的 WHERE 条件中包含多个 PART,例如
WHERE e.Job LIKE 'TEMPLATE%' AND e.Material IN ('PART1', 'PART2', ..., 'PART99')
生成的表格将难以导航。
我希望能够以某种方式附加递归行源自的原始锚“部分”。这甚至可能吗?我无法理解如何。结果表如下所示:
n | Job | Part_Number | Material | Anchor |
---|---|---|---|---|
0 | TEMP1 | PART1 | PART1a | PART1 |
0 | TEMP1 | PART1 | PART1b | PART1 |
0 | TEMP8 | PART2 | PART2a | PART2 |
1 | TEMP2 | PART1a | MATERIAL1 | PART1 |
1 | TEMP3 | PART1b | PART1b1 | PART1 |
1 | TEMP9 | PART2a | PART2a1 | PART2 |
2 | TEMP4 | PART1b1 | PART1b1a | PART1 |
2 | TEMP10 | PART2a1 | MATERIAL7 | PART2 |
3 | TEMP5 | PART1b1a | MATERIAL2 | PART1 |
【问题讨论】:
您可以使用相关表格中的任何可用列。所以你需要给with q (..., Material) as (...
添加额外的列,定义为Material
是锚select
,然后再从q
拉出来
【参考方案1】:
如果我理解正确,您只需在“上”SELECT
中暴露两次Part_Number
列,然后将CTE 的列放在“下”之一中:
WITH q AS
(SELECT 0 AS n,
Material.Part_Number,
Material_Req.Job,
Material_Req.Material,
Material.Part_Number AS Anchor
FROM Production.dbo.Material_Req
INNER JOIN PRODUCTION.dbo.Material ON Material_Req.Job = Material.Job
WHERE e.Job LIKE 'TEMPLATE%'
AND e.Material IN ('PART1')
UNION ALL
SELECT n + 1,
Material.Part_Number,
Material_Req.Job,
Material_Req.Material,
q.Anchor
FROM Production.dbo.Material_Req
INNER JOIN PRODUCTION.dbo.Material ON Material_Req.Job = Material.Job
INNER JOIN q ON q.Material = Material.Material
WHERE Material.Job LIKE 'TEMPLATE%')
SELECT DISTINCT
n,
Job,
Part_Number,
Material,
anchor
FROM q
WHERE Job LIKE 'TEMPLATE%'
ORDER BY n;
【讨论】:
q (n, Part_Number, Job, Material)
,所以它不应该有 anchor
列。还是我遗漏了一些特定于 T-SQL 的内容?
应该,我很少(从不)在我的WITH
子句中定义列,所以我错过了添加它,@astentx。相反,我给第一列一个别名,并在 WITH
中删除了别名
漂亮,非常感谢。 CTE 和 SQL 中的递归对我来说都是新的,所以我仍在尝试理解如何做不同的事情。太快了,我无法批准作为答案,哈哈以上是关于如何在 CTE 的所有递归行上提取相关的“锚”值的主要内容,如果未能解决你的问题,请参考以下文章