如何在Snowflake中创建递归连接

huangapple go评论65阅读模式
英文:

How to create a recursive join in snowflake

问题

我有一个查询,其中包括多个左连接以获取员工的管理层次列表。我知道Snowflake有递归功能,但我在理解上有困难。有人知道如何递归地编写类似这样的查询吗?

select
    d1.employee_id,
    d1.employee_id1,
    d1.employee_id2,
    d1.employee_id3,
    d2.employee_id1 as employee_id4,
    d2.manager_name as employee_id4_name,
    d3.employee_id1 as employee_id5,
    d3.manager_name as employee_id5_name,
    d4.employee_id1 as employee_id6,
    d4.manager_name as employee_id6_name,
    d5.employee_id1 as employee_id7,
    d5.manager_name as employee_id7_name
from employees d1
left join employees d2
on d1.employee_id3 = d2.employee_id
and d1.report_effective_date = d2.report_effective_date
left join employees d3
on d2.employee_id1 = d3.employee_id
and d2.report_effective_date = d3.report_effective_date
left join employees d4
on d3.employee_id1 = d4.employee_id
and d3.report_effective_date = d4.report_effective_date
left join employees d5
on d4.employee_id1 = d5.employee_id
and d4.report_effective_date = d5.report_effective_date

根据我理解的方式,我尝试过以下内容,但似乎无法按我希望的格式排列?我想要获取个人的管理层次结构,但每个经理都在一个新列中。

with cte as (
  select
    employee_id,
    employee_name,
    employee_id1,
    manager_name
  from employees
  where employee_name = <name>
  
  union all

  select
    employee.employee_id,
    employee.employee_name,
    employee.employee_id1,
    employee.manager_name
  from employees
  join cte
  on employee.employee_id = cte.employee_id1
)
select * from cte
英文:

I have a query with a bunch of left joins to get a hierarchal list of managers for an employee. I know snowflake has a recursive functionality but having trouble following. Does anyone know how something like this can be written recursively?

select
    d1.employee_id,
    d1.employee_id1,
    d1.employee_id2,
    d1.employee_id3,
    d2.employee_id1 as employee_id4,
    d2.manager_name as employee_id4_name,
    d3.employee_id1 as employee_id5,
    d3.manager_name as employee_id5_name,
    d4.employee_id1 as employee_id6,
    d4.manager_name as employee_id6_name,
    d5.employee_id1 as employee_id7,
    d5.manager_name as employee_id7_name
from employees d1
left join employees d2
on d1.employee_id3 = d2.employee_id
and d1.report_effective_date = d2.report_effective_date
left join employees d3
on d2.employee_id1 = d3.employee_id
and d2.report_effective_date = d3.report_effective_date
left join employees d4
on d3.employee_id1 = d4.employee_id
and d3.report_effective_date = d4.report_effective_date
left join employees d5
on d4.employee_id1 = d5.employee_id
and d4.report_effective_date = d5.report_effective_date

Edit with what I've tried - and from my understanding the way I want this formatted doesn't seem possible? I'm looking to get an individual's manager hierarchy but with each manager in a new column.

What I tried was like this, but it would give me the hierarchy in rows and would require that I have an anchored query filtered to someone.

with cte as (
  select
    employee_id,
    employee_name,
    employee_id1,
    manager_name
  from employees
  where employee_name = &lt;name&gt;
  
  union all

  select
    employee.employee_id,
    employee.employee_name,
    employee.employee_id1,
    employee.manager_name
  from employees
  join cte
  on employee.employee_id = cte.employee_id1
)
select * from cte

答案1

得分: 1

你说得对,你会得到行而不是列。你还说得对,你需要在查询中锚定某个人或某个群体。考虑将一个没有分配employee_id1的员工作为锚点(如果我理解你的数据的话,这个员工是组织中的最高层)。

至于"Data in rows",考虑构建一个层次路径,你可以将其拆分成数组或其他形式:

with cte as (
  select
    employee_id as employee,
    employee_name,
    employee_id1 as manager,
    manager_name,
    CAST(employee_id AS VARCHAR(500)) as path,
    1 as depth
  from employees
  where employee_id1 IS NULL
  
  union all

  select
    employee.employee_id,
    employee.employee_name,
    employee.employee_id1,
    employee.manager_name,
    cte.path || '>' || employee.employee_id,
    cte.depth + 1
  from employees
  join cte
  on employee.employee_id = cte.employee_id1
)
select * from cte

现在你有了员工的完整路径以及该员工的深度,这应该会有很大帮助。

英文:

You are correct that you would get back rows instead of columns. You are also correct that you would need to anchor the query on someone, or some group. Consider, as an anchor, an employee that has no employee_id1 assigned (The top most person in the org, if I understand your data).

As for the "Data in rows" consider building a hierarchical path that you can split to an array or what-have-you:

with cte as (
  select
    employee_id as employee,
    employee_name,
    employee_id1 as manager,
    manager_name,
    CAST(employee_id AS VARCHAR(500)) as path,
    1 as depth
  from employees
  where employee_id1 IS NULL
  
  union all

  select
    employee.employee_id,
    employee.employee_name,
    employee.employee_id1,
    employee.manager_name,
    cte.path || &#39;&gt;&#39; || employee.employee_id,
    cte.depth + 1
  from employees
  join cte
  on employee.employee_id = cte.employee_id1
)
select * from cte

Now you have the full path for the employee as well as the depth of that employee, which should help plenty.

huangapple
  • 本文由 发表于 2023年6月15日 03:41:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76477041.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定