在 SQL 服务器中使用数据透视和递归代码改进查询
Improve a query with Pivot and Recursive code in SQL Server
考虑到这两个 table,我需要达到下一个结果。
一个地区接受不同部门的服务。每个部门都属于三个(或更少)级别的层次结构。这个想法是在一列中表示该区域与其可能存在的所有层次结构之间的关系。对于没有父亲的记录,Level Nro 应该为 1。
到目前为止,我有这段代码 https://rextester.com/KYHKR17801 。我得到了我需要的结果。但是,性能不是最好的,因为 table 太大了,我不得不做很多转换:
- 枢轴
- 递归
- 添加寄存器,因为我在创建数据透视表时丢失了空值table
- 更新关卡Nro
如果有人可以提供任何建议来改进此查询的运行时间,我不会。
这似乎在一条语句中完成了您需要的一切:
WITH R AS
(
SELECT
SA.AreaID,
S.[service],
S.[description],
L.[Level],
L.child_service,
Recursion = 1
FROM dbo.service_area AS SA
JOIN dbo.[service] AS S
ON S.[service] = SA.[Service]
OUTER APPLY
(
-- Unpivot
VALUES
(1, S.level1),
(2, S.level2),
(3, S.level3)
) AS L ([Level], child_service)
WHERE
L.child_service IS NOT NULL
UNION ALL
SELECT
R.AreaID,
S.[service],
S.[description],
R.[Level],
child_service = CHOOSE(R.[Level], S.level1, S.level2, S.level3),
Recursion = R.Recursion + 1
FROM R
JOIN dbo.[service] AS S
ON S.[service] = R.child_service
)
SELECT
R.AreaID,
R.[service],
R.[description],
[Level] = 'Level' + CONVERT(char(1), R.[Level]),
[Level Nro] = ROW_NUMBER() OVER (
PARTITION BY R.AreaID, R.[Level]
ORDER BY R.Recursion DESC)
FROM R
ORDER BY
R.AreaID ASC,
R.[Level] ASC,
[Level Nro]
OPTION (MAXRECURSION 3);
以下索引将帮助递归部分快速定位行:
CREATE UNIQUE CLUSTERED INDEX cuq ON dbo.[service] ([service]);
如果你的SQL服务器版本没有CHOOSE
,手写CASE
语句:
CASE R.[Level] WHEN 1 THEN S.level1 WHEN 2 THEN S.level2 ELSE S.level3 END
考虑到这两个 table,我需要达到下一个结果。
一个地区接受不同部门的服务。每个部门都属于三个(或更少)级别的层次结构。这个想法是在一列中表示该区域与其可能存在的所有层次结构之间的关系。对于没有父亲的记录,Level Nro 应该为 1。
到目前为止,我有这段代码 https://rextester.com/KYHKR17801 。我得到了我需要的结果。但是,性能不是最好的,因为 table 太大了,我不得不做很多转换:
- 枢轴
- 递归
- 添加寄存器,因为我在创建数据透视表时丢失了空值table
- 更新关卡Nro
如果有人可以提供任何建议来改进此查询的运行时间,我不会。
这似乎在一条语句中完成了您需要的一切:
WITH R AS
(
SELECT
SA.AreaID,
S.[service],
S.[description],
L.[Level],
L.child_service,
Recursion = 1
FROM dbo.service_area AS SA
JOIN dbo.[service] AS S
ON S.[service] = SA.[Service]
OUTER APPLY
(
-- Unpivot
VALUES
(1, S.level1),
(2, S.level2),
(3, S.level3)
) AS L ([Level], child_service)
WHERE
L.child_service IS NOT NULL
UNION ALL
SELECT
R.AreaID,
S.[service],
S.[description],
R.[Level],
child_service = CHOOSE(R.[Level], S.level1, S.level2, S.level3),
Recursion = R.Recursion + 1
FROM R
JOIN dbo.[service] AS S
ON S.[service] = R.child_service
)
SELECT
R.AreaID,
R.[service],
R.[description],
[Level] = 'Level' + CONVERT(char(1), R.[Level]),
[Level Nro] = ROW_NUMBER() OVER (
PARTITION BY R.AreaID, R.[Level]
ORDER BY R.Recursion DESC)
FROM R
ORDER BY
R.AreaID ASC,
R.[Level] ASC,
[Level Nro]
OPTION (MAXRECURSION 3);
以下索引将帮助递归部分快速定位行:
CREATE UNIQUE CLUSTERED INDEX cuq ON dbo.[service] ([service]);
如果你的SQL服务器版本没有CHOOSE
,手写CASE
语句:
CASE R.[Level] WHEN 1 THEN S.level1 WHEN 2 THEN S.level2 ELSE S.level3 END