【问题标题】:CONNECT BY or hierarchical queries in RDBMS other than Oracle除 Oracle 之外的 RDBMS 中的 CONNECT BY 或分层查询
【发布时间】:2011-09-18 01:50:40
【问题描述】:

Oracle 附带了一个非常方便的特性。您可以使用以下子句创建分层查询(递归行为):

CONNECT BY [NOCYCLE] {condition [AND condition...]} [START WITH condition]

如此处所述:

http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/queries003.htm

我想知道,是否有任何其他已建立的 RDBMS 支持等效或类似的语法?或者可以使用常规 SQL 来模拟这种递归行为吗?

我希望能够模拟的一个很好的例子是这个(取自 Oracle 文档):

    SELECT LPAD(' ', 2 * (LEVEL-1)) || last_name org_chart, 
           employee_id, manager_id, job_id
      FROM employees
START WITH job_id = 'AD_VP' 
CONNECT BY PRIOR employee_id = manager_id; 

导致:

ORG_CHART          EMPLOYEE_ID MANAGER_ID JOB_ID
------------------ ----------- ---------- ----------
Kochhar                    101        100 AD_VP
  Greenberg                108        101 FI_MGR
    Faviet                 109        108 FI_ACCOUNT
    Chen                   110        108 FI_ACCOUNT
    Sciarra                111        108 FI_ACCOUNT
    Urman                  112        108 FI_ACCOUNT
    Popp                   113        108 FI_ACCOUNT
  Whalen                   200        101 AD_ASST
  Mavris                   203        101 HR_REP
  Baer                     204        101 PR_REP
  Higgins                  205        101 AC_MGR
    Gietz                  206        205 AC_ACCOUNT
De Haan                    102        100 AD_VP
  Hunold                   103        102 IT_PROG
    Ernst                  104        103 IT_PROG
    Austin                 105        103 IT_PROG
    Pataballa              106        103 IT_PROG
    Lorentz                107        103 IT_PROG

LEVEL 伪列和用它实现的缩进对我来说并不那么重要

【问题讨论】:

    标签: sql oracle simulation recursive-query connect-by


    【解决方案1】:

    SQL Server 使用通用表表达式(WITH 语句)来实现相同的目的(参见Recursive Queries Using Common Table Expressions)。

    这种查询在Oracle中也可以使用(如果我没记错的话是11g开头的)。

    生成的查询更复杂:

    WITH emp(employee_id, manager_id, job_id, last_name, lvl)
    AS (
        SELECT e.employee_id, e.manager_id, e.job_id, e.last_name, 1 lvl
        FROM employees e
        WHERE job_id = 'AD_VP'
        UNION ALL
        SELECT e.employee_id, e.manager_id, e.job_id, e.last_name, r.lvl + 1 lvl
        FROM employees e
        JOIN emp r ON r.employee_id = e.manager_id
    )
    SELECT LPAD(' ', 2 * (lvl-1)) || last_name org_chart,
        employee_id, manager_id, job_id
    FROM emp;
    

    【讨论】:

    • 啊,这很有趣。我从来没有这样想过WITH 子句。所以原则上,这种方法没有那么强大(因为更冗长),但更通用?其他支持 WITH 子句的 RDBMS(将来)也支持此功能的可能性很高...
    • 非常非常好。谢谢你的例子!
    • 完成图片:递归 CTE 在 Firebird、PostgreSQL、DB2、Teradata 和 Sybase 中可用(我认为 H2 也是如此)
    • 嗯@Codo,我又想知道这些事情了。在jooq.org 中,我已经支持Oracle 的CONNECT BY 语法:sourceforge.net/apps/trac/jooq/wiki/Manual/ADVANCED/CONNECTBY。现在,我想为其他 RDBMS 模拟 Oracle 的 CONNECT BY 语法(除了支持 WITH 子句本身)。您认为可以实现从更简单的CONNECT BY 子句(有或没有STARTS WITH)到CTE 的正式转换吗?对于 jOOQ 来说,这将是一个很棒的功能......!
    【解决方案2】:

    developerworks 网站Port CONNECT BY to DB2 上有一篇文章进行了很好的转换。 还有一篇关于 Explain Extended(Quassnoi 的博客)的有趣文章,显示了 CONNECT BY 和递归 CTE 之间的一些区别:Adjacency list vs. nested sets: Oracle,基于行和基于集合。他还有一篇关于“SQL Server: are the recursive CTE's really set-based?”的好文章。似乎“Oracle 中的递归 CTE 也不是基于集合的”。我希望这有助于 JOOQ 中的转换、递归以及理解 SQL 中递归的两种实现的区别。

    问候, JJ。

    【讨论】:

    • 这是 developerworks 提供的一个非常好的资源!我喜欢它解释所有涉及的关键字以及如何将它们应用于递归 CTE 的方式。有了这个资源,我终于可以解决jooq.org中的模拟了!
    【解决方案3】:

    对 SO 的拖网显示了以下问题和答案,这些问题和答案处理了对各种数据库的分层查询。最后一个引用了MySql resource,它提供了一个通用的 SQL 方法。

    Building a Table Dependency Graph With A Recursive Query

    Recursive select in SQL

    SQL recursive query

    Generating Depth based tree from Hierarchical Data in MySQL (no CTEs)

    【讨论】:

    • 感谢您的提示。这是来自 MySQL 的一个很好的资源
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-07
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 2013-05-27
    相关资源
    最近更新 更多