繁体   English   中英

递归查询 presto SQL

[英]recursive query presto SQL

我需要找到他们没有使用 PRESTO SQL 向其报告的最后一位最高教师(每个人的最高教师必须是 teacher_id 7)的 teacher_id。 层次结构深度可以大于示例数据集中显示的深度。

查询结果必须发出teacher_id: 8,9,10,11

输出:

教师全名 老师_id
简·奥尔特戈 8个
鲍尔斯 9
李莎莎 10
黛安娜·诺里斯 11

示例数据集:

教师全名 教师编号 记者_老师
玛格福尔摩斯 1个 2个
携带里程 2个 3个
菲利普巴斯科夫 3个 4个
哈利·波特 4个 5个
丹尼尔洛佩兹 5个 6个
伊万彼得罗夫 6个 7
Jhon Doe 7
简·奥尔特戈 8个 9
鲍尔斯 9 10
李莎莎 10 9
黛安娜·诺里斯 11 10
怀特 12 6个

我用PostgreSQL来实现这样的递归逻辑,但我不知道如何在Presto中实现。

AFAIK Presto 不支持递归查询,如果您可以迁移到Trino ,则可以使用WITH RECURSIVE CTE 子句 我的看法是这样的(可能可以优化):

with recursive dataset(teacher_full_name, teacher_id, reporter_teacher) as(
    values ('Margo Holmes', 1,  2),
        ('Carry Miles',     2,  3),
        ('Philipp Baskov',  3,  4),
        ('Harry Potter',    4,  5),
        ('Daniel Lopez',    5,  6),
        ('Ivan Petrov',     6,  7),
        ('Jhon Doe',        7,  null),
        ('Jane Ortego',     8,  9),
        ('Michael Powers',  9,  10),
        ('Sasha Li',        10, 9),
        ('Diana Norris',    11, 10),
        ('Wolter White',    12, 6)
),
t(lvl, teacher_full_name, teacher_id, reporter_teacher, all_parents) as(
    select 1 lvl, teacher_full_name, teacher_id, reporter_teacher, array[reporter_teacher] all_parents
    from dataset
    union all
    select t.lvl +1,
        t.teacher_full_name,
        t.teacher_id,
        d.reporter_teacher,
        d.reporter_teacher || t.all_parents as all_parents
    from dataset d
    inner join t on t.reporter_teacher = d.teacher_id
    where not contains(all_parents, d.reporter_teacher)
)

select arbitrary(t.teacher_full_name) full_name,
       t.teacher_id
from t
group by t.teacher_id
having not contains(max_by(t.all_parents, t.lvl), 7)
order by teacher_id;

输出:

全名 教师编号
简·奥尔特戈 8个
鲍尔斯 9
李莎莎 10
黛安娜·诺里斯 11

不幸的是,Presto 不支持递归 CTE ,所以你能做的最好的可能就是它们的链。 是这样的:

WITH R1 AS (
    SELECT teacher_id
    FROM @input
    WHERE reporter_teacher IS NULL
),
R2 AS (
    SELECT i.teacher_id
    FROM @input i
    INNER JOIN R1 ON i.reporter_teacher=R1.teacher_id
),
R3 AS (
    SELECT i.teacher_id
    FROM @input i
    INNER JOIN R2 ON i.reporter_teacher=R2.teacher_id
)

--R4 AS ... referencing R3
--R5 AS ... referencing R4

SELECT * FROM @input WHERE teacher_id NOT IN (
    SELECT * FROM R1
    UNION SELECT * FROM R2
    UNION SELECT * FROM R3
    --UNION SELECT * FROM R4 etc
)

由于您已经说过层次结构深度可能比数据集中显示的更大,因此您的表达式中需要更多 CTE。

快速解释这是如何工作的:

R1选择所有不向任何人报告的员工,因此在样本数据中, Jhon Doe

R2选择向R1中的员工报告的所有员工。 在示例中, Ivan Petrov因为他向Jhon Doe报告。 依此类推。 递归得足够远,您最终将获得向Jhon Doe报告的所有员工。

最后一位合并所有R_n ,为您提供要从最终选择中排除的人员列表。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM