我是使用 postgresql 的新手,正在寻找有关如何将 MySql 中的这些 vars 用法转换为 Postgres 的帮助,看起来 postgres 不支持这种类型的语法。
select
name
from
(
select
@lidx := field(
coalesce(
@root_id, coalesce(p10.id,p9.id,p8.id,p7.id,p6.id,p5.id,p4.id,p3.id,p2.id,p1.id)
),
p1.id,p2.id,p3.id,p4.id,p5.id,p6.id,p7.id,p8.id,p9.id,p10.id
) as leftmost,
concat(
if(@lidx >= 10, rpad(p10.name, 24, ' '), ''),
if(@lidx >= 9, rpad(p9.name, 24, ' '), ''),
if(@lidx >= 8, rpad(p8.name, 24, ' '), ''),
if(@lidx >= 7, rpad(p7.name, 24, ' '), ''),
if(@lidx >= 6, rpad(p6.name, 24, ' '), ''),
if(@lidx >= 5, rpad(p5.name, 24, ' '), ''),
if(@lidx >= 4, rpad(p4.name, 24, ' '), ''),
if(@lidx >= 3, rpad(p3.name, 24, ' '), ''),
if(@lidx >= 2, rpad(p2.name, 24, ' '), ''),
rpad(p1.name, 24, ' ')
) as locator,
-- Prepend a tab to the name for every level of the tree after the root.
concat(repeat('\\t', @lidx - 1), p1.name) as name
from
(
-- Declare constants
select
-- company_id. Leave null for all companies
@company_id := null,
-- root_id. Leave null for all departments
@root_id := null
) sqlVars,
hierarchy p1
-- repeatedly left join until the desired max depth (10)
left join hierarchy p2 on p2.id = p1.parent_id
left join hierarchy p3 on p3.id = p2.parent_id
left join hierarchy p4 on p4.id = p3.parent_id
left join hierarchy p5 on p5.id = p4.parent_id
left join hierarchy p6 on p6.id = p5.parent_id
left join hierarchy p7 on p7.id = p6.parent_id
left join hierarchy p8 on p8.id = p7.parent_id
left join hierarchy p9 on p9.id = p8.parent_id
left join hierarchy p10 on p10.id = p9.parent_id
where
( -- filter on company_id if non null
@company_id is null
or @company_id = p1.company_id
)
and ( -- filter on root_id if non null
@root_id is null
or @root_id in (p1.id,p2.id,p3.id,p4.id,p5.id,p6.id,p7.id,p8.id,p9.id,p10.id)
)
-- alpha ordering
order by
locator
) flattened;
要检查当前的 SQL 和使用情况并运行它,请使用下面的 sql fiddle
SQL Fiddle[1]:http://sqlfiddle.com/#!9/faf62e/200
您可以使用递归查询:
with recursive tree as (
select name, id, 0 as level
from hierarchy
where parent_id is null
union all
select c.name, c.id, p.level + 1
from hierarchy c
join tree p on p.id = c.parent_id
)
search depth first by name set sort_order
select repeat(' ', level * 2)||name
from tree
order by sort_order;
通过使用
search depth first
,我们可以将子树保持在一起。
请注意,我使用空格来实现缩进,因为 dbFiddle 中未显示制表符。
接近:
with recursive tree (id, name, level) as (
select id, name, 0 from hierarchy where parent_id is null
union all
select hierarchy.id, hierarchy.name, tree.level+1
from hierarchy join tree on hierarchy.parent_id = tree.id
)
select repeat('\t', level) || name from tree order by id;
它不会重现与您的 sqlfiddle 完全相同的行顺序,但这是在 PostgreSQL(或 MySQL 8.0)中进行递归查询的方法。
阅读手册以获取有关递归 CTE 语法的更多信息:https://www.postgresql.org/docs/current/queries-with.html#QUERIES-WITH-RECURSIVE