在递归 SQL 查询中对多个 Parent/Child 进行排序
Sorting Multiple Parent/Child on Recursive SQL Query
我正在将一些 Oracle 代码转换为 SQL 服务器。
Oracle 代码如下所示:
SELECT FLEX_VALUE, DESCRIPTION, ADMIN_ENABLED, PARENT_FLEX_VALUE, DISPLAY_DESC, LEVEL
FROM ( SELECT FLEX_VALUE, DESCRIPTION, ADMIN_ENABLED, PARENT_FLEX_VALUE, vDescField AS DISPLAY_DESC
FROM GL_SEGMENT2
WHERE PERIOD_YEAR = 2015; )
CONNECT BY PRIOR FLEX_VALUE = PARENT_FLEX_VALUE
START WITH PARENT_FLEX_VALUE IS NULL
ORDER SIBLINGS BY DISPLAY_DESC;
它产生了以下正确的结果:
查询按 parent 对数据进行分组,并指示级别。
结果按 parent 组排序。
组标题下的 'children' 似乎没有排序。
数据存储在单个 table.
中
我已将 Oracle 查询转换为以下 SQL 服务器查询:
WITH n ([FLEX_VALUE], [DESCRIPTION], [ADMIN_ENABLED], [PARENT_FLEX_VALUE], [DISPLAY_DESC], [LEVEL]) AS
(SELECT P1.[FLEX_VALUE], P1.[DESCRIPTION], P1.[ADMIN_ENABLED], P1.[PARENT_FLEX_VALUE], P1.[DISPLAY_DESC], 1 AS [LEVEL]
FROM (SELECT [FLEX_VALUE], [DESCRIPTION], [ADMIN_ENABLED], [PARENT_FLEX_VALUE], [FLEX_VALUE] + ' - ' + [DESCRIPTION] AS [DISPLAY_DESC]
FROM dbo.FIN_REP_GL_SEGMENT2
WHERE [PERIOD_YEAR] = 2015 ) AS P1
WHERE LEN(LTRIM(RTRIM(ISNULL(P1.[PARENT_FLEX_VALUE],'')))) = 0
UNION ALL
SELECT C1.[FLEX_VALUE], C1.[DESCRIPTION], C1.[ADMIN_ENABLED], C1.[PARENT_FLEX_VALUE], C1.[DISPLAY_DESC], Parent.[LEVEL] + 1
FROM (SELECT [FLEX_VALUE], [DESCRIPTION], [ADMIN_ENABLED], [PARENT_FLEX_VALUE], [FLEX_VALUE] + ' - ' + [DESCRIPTION] AS [DISPLAY_DESC]
FROM dbo.FIN_REP_GL_SEGMENT2
WHERE [PERIOD_YEAR] = 2015 ) AS C1
JOIN n Parent ON Parent.[FLEX_VALUE] = C1.[PARENT_FLEX_VALUE] )
SELECT [FLEX_VALUE], [DESCRIPTION], [ADMIN_ENABLED], [PARENT_FLEX_VALUE], [DISPLAY_DESC], [LEVEL]
FROM n
ORDER BY [DISPLAY_DESC]
上面的 SQL 服务器查询产生 INCORRECT SORTING,如下图所示:
级别似乎正确,但 children 显示在不正确的 parent 类别下 (注意 B145 和 Cnnn 值)。 B145记录应显示在F000parent下方,Cnnn记录应显示在L000parent下方。
目前 SQL 查询将这些放在 B000 parent 下,这是不正确的!
SQL 查询似乎在 FLEX_VALUE 列上排序,而不管 'parent' 'child' 实际上属于什么。
问题的根本原因[原文如此]似乎是 MULTIPLE 个根记录 PARENT_FLEX_VALUE,实际上我想忽略 FLEX_VALUE 上的字母排序(我只关心 PARENT 排序顺序).
我对 SQL 查询所做的一切尝试都没有改变排序顺序。
除 sorting/grouping 问题外,查询基本正常。
非常感谢我当前 SQL 服务器查询尝试的 re-worked 示例,并解释为什么它当前不起作用。
这个 Oracle 查询类似于您的递归查询,应该有所帮助。我想你可以轻松修改为 SQL 服务器版本:
with t(FV, DSC, PFV, path, lvl) as (
select FLEX_VALUE, DESCRIPTION, PARENT_FLEX_VALUE, flex_value, 1
from gl_segment2 where parent_flex_value is null
union all
select g.FLEX_VALUE, g.DESCRIPTION, g.PARENT_FLEX_VALUE,
t.path||'/'||g.flex_value, t.lvl+1
from gl_segment2 g join t on g.parent_flex_value = t.fv )
select t.*, lpad(' ', (lvl-1)*2, ' ')||fv hierarchy from t order by path
为了保持层次结构,我添加了 path
列以实现正确的排序。
当然,您不需要输出中的 PATH、LVL、HIERARCHY 列,我添加它们只是为了演示目的。
输出和SQLFiddle:
FV DSC PFV PATH LVL HIERARCHY
----- -------------------- ----- ----------------- ---------- ----------
A000 DESCRIPTION A000 A000 1 A000
A010 DESCRIPTION A010 A000 A000/A010 2 A010
A100 DESCRIPTION A100 A010 A000/A010/A100 3 A100
A101 DESCRIPTION A101 A010 A000/A010/A101 3 A101
A011 DESCRIPTION A011 A000 A000/A011 2 A011
B000 DESCRIPTION B000 B000 1 B000
B010 DESCRIPTION B010 B000 B000/B010 2 B010
B011 DESCRIPTION B011 B000 B000/B011 2 B011
F000 DESCRIPTION F000 F000 1 F000
B145 DESCRIPTION B145 F000 F000/B145 2 B145
我正在将一些 Oracle 代码转换为 SQL 服务器。
Oracle 代码如下所示:
SELECT FLEX_VALUE, DESCRIPTION, ADMIN_ENABLED, PARENT_FLEX_VALUE, DISPLAY_DESC, LEVEL
FROM ( SELECT FLEX_VALUE, DESCRIPTION, ADMIN_ENABLED, PARENT_FLEX_VALUE, vDescField AS DISPLAY_DESC
FROM GL_SEGMENT2
WHERE PERIOD_YEAR = 2015; )
CONNECT BY PRIOR FLEX_VALUE = PARENT_FLEX_VALUE
START WITH PARENT_FLEX_VALUE IS NULL
ORDER SIBLINGS BY DISPLAY_DESC;
它产生了以下正确的结果:
查询按 parent 对数据进行分组,并指示级别。 结果按 parent 组排序。 组标题下的 'children' 似乎没有排序。 数据存储在单个 table.
中我已将 Oracle 查询转换为以下 SQL 服务器查询:
WITH n ([FLEX_VALUE], [DESCRIPTION], [ADMIN_ENABLED], [PARENT_FLEX_VALUE], [DISPLAY_DESC], [LEVEL]) AS
(SELECT P1.[FLEX_VALUE], P1.[DESCRIPTION], P1.[ADMIN_ENABLED], P1.[PARENT_FLEX_VALUE], P1.[DISPLAY_DESC], 1 AS [LEVEL]
FROM (SELECT [FLEX_VALUE], [DESCRIPTION], [ADMIN_ENABLED], [PARENT_FLEX_VALUE], [FLEX_VALUE] + ' - ' + [DESCRIPTION] AS [DISPLAY_DESC]
FROM dbo.FIN_REP_GL_SEGMENT2
WHERE [PERIOD_YEAR] = 2015 ) AS P1
WHERE LEN(LTRIM(RTRIM(ISNULL(P1.[PARENT_FLEX_VALUE],'')))) = 0
UNION ALL
SELECT C1.[FLEX_VALUE], C1.[DESCRIPTION], C1.[ADMIN_ENABLED], C1.[PARENT_FLEX_VALUE], C1.[DISPLAY_DESC], Parent.[LEVEL] + 1
FROM (SELECT [FLEX_VALUE], [DESCRIPTION], [ADMIN_ENABLED], [PARENT_FLEX_VALUE], [FLEX_VALUE] + ' - ' + [DESCRIPTION] AS [DISPLAY_DESC]
FROM dbo.FIN_REP_GL_SEGMENT2
WHERE [PERIOD_YEAR] = 2015 ) AS C1
JOIN n Parent ON Parent.[FLEX_VALUE] = C1.[PARENT_FLEX_VALUE] )
SELECT [FLEX_VALUE], [DESCRIPTION], [ADMIN_ENABLED], [PARENT_FLEX_VALUE], [DISPLAY_DESC], [LEVEL]
FROM n
ORDER BY [DISPLAY_DESC]
上面的 SQL 服务器查询产生 INCORRECT SORTING,如下图所示:
级别似乎正确,但 children 显示在不正确的 parent 类别下 (注意 B145 和 Cnnn 值)。 B145记录应显示在F000parent下方,Cnnn记录应显示在L000parent下方。 目前 SQL 查询将这些放在 B000 parent 下,这是不正确的!
SQL 查询似乎在 FLEX_VALUE 列上排序,而不管 'parent' 'child' 实际上属于什么。
问题的根本原因[原文如此]似乎是 MULTIPLE 个根记录 PARENT_FLEX_VALUE,实际上我想忽略 FLEX_VALUE 上的字母排序(我只关心 PARENT 排序顺序).
我对 SQL 查询所做的一切尝试都没有改变排序顺序。
除 sorting/grouping 问题外,查询基本正常。
非常感谢我当前 SQL 服务器查询尝试的 re-worked 示例,并解释为什么它当前不起作用。
这个 Oracle 查询类似于您的递归查询,应该有所帮助。我想你可以轻松修改为 SQL 服务器版本:
with t(FV, DSC, PFV, path, lvl) as (
select FLEX_VALUE, DESCRIPTION, PARENT_FLEX_VALUE, flex_value, 1
from gl_segment2 where parent_flex_value is null
union all
select g.FLEX_VALUE, g.DESCRIPTION, g.PARENT_FLEX_VALUE,
t.path||'/'||g.flex_value, t.lvl+1
from gl_segment2 g join t on g.parent_flex_value = t.fv )
select t.*, lpad(' ', (lvl-1)*2, ' ')||fv hierarchy from t order by path
为了保持层次结构,我添加了 path
列以实现正确的排序。
当然,您不需要输出中的 PATH、LVL、HIERARCHY 列,我添加它们只是为了演示目的。
输出和SQLFiddle:
FV DSC PFV PATH LVL HIERARCHY
----- -------------------- ----- ----------------- ---------- ----------
A000 DESCRIPTION A000 A000 1 A000
A010 DESCRIPTION A010 A000 A000/A010 2 A010
A100 DESCRIPTION A100 A010 A000/A010/A100 3 A100
A101 DESCRIPTION A101 A010 A000/A010/A101 3 A101
A011 DESCRIPTION A011 A000 A000/A011 2 A011
B000 DESCRIPTION B000 B000 1 B000
B010 DESCRIPTION B010 B000 B000/B010 2 B010
B011 DESCRIPTION B011 B000 B000/B011 2 B011
F000 DESCRIPTION F000 F000 1 F000
B145 DESCRIPTION B145 F000 F000/B145 2 B145