【问题标题】:What is the equivalent PostgreSQL syntax to Oracle's CONNECT BY ... START WITH?与 Oracle 的 CONNECT BY ... START WITH 等效的 PostgreSQL 语法是什么?
【发布时间】:2014-07-22 22:06:10
【问题描述】:

Oracle 中,如果我有一个表定义为……

CREATE TABLE taxonomy
    (
    key NUMBER(11) NOT NULL CONSTRAINT taxPkey PRIMARY KEY,
    value VARCHAR2(255),
    taxHier NUMBER(11)
    );
ALTER TABLE
    taxonomy
ADD CONSTRAINT
    taxTaxFkey
FOREIGN KEY
    (taxHier)
REFERENCES
    tax(key);

有了这些值……

key value   taxHier
0   zero    null
1   one     0
2   two     0
3   three   0
4   four    1
5   five    2
6   six     2

这个查询语法……

SELECT
     value
FROM
    taxonomy
CONNECT BY
    PRIOR key = taxHier
START WITH
    key = 0;

将产生……

zero
one
four
two
five
six
three

这是如何在 PostgreSQL 中完成的?

【问题讨论】:

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


【解决方案1】:

在 Postgres 中使用 RECURSIVE CTE

WITH RECURSIVE cte AS (
   SELECT key, value, 1 AS level
   FROM   taxonomy
   WHERE  key = 0

   UNION  ALL
   SELECT t.key, t.value, c.level + 1
   FROM   cte      c
   JOIN   taxonomy t ON t.taxHier = c.key
   )
SELECT value
FROM   cte
ORDER  BY level;

我之前的回答中的详细信息和文档链接:

【讨论】:

【解决方案2】:

Postgres 确实有一个相当于 connect by。您将需要启用该模块。它默认关闭。

它被称为 tablefunc。它支持一些很酷的交叉表功能以及熟悉的“connect by”和“Start With”。我发现它比递归 CTE 更有说服力和逻辑性。如果您的 DBA 无法启用此功能,则应采用 Erwin 的做法。
它也足够强大,可以进行“材料清单”类型的查询。

运行这个命令可以开启Tablefunc:

CREATE EXTENSION tablefunc;

这里是从官方文档中新提取的连接字段列表。

Parameter:         Description
relname:           Name of the source relation (table)
keyid_fld:         Name of the key field
parent_keyid_fld:  Name of the parent-key field
orderby_fld:       Name of the field to order siblings by (optional)
start_with:        Key value of the row to start at
max_depth:         Maximum depth to descend to, or zero for unlimited depth
branch_delim:      String to separate keys with in branch output (optional)

您真的应该看看文档页面。它写得很好,它会给你你习惯的选项。 (在文档页面向下滚动,靠近底部。)

Postgreql "Connect by" extension 以下是对该结构的组合应该是什么样的描述。有很多潜力,所以我不会公正地对待它,但这里有一个片段可以给你一个想法。

connectby(text relname, text keyid_fld, text parent_keyid_fld
          [, text orderby_fld ], text start_with, int max_depth
          [, text branch_delim ])

真正的查询将如下所示。 Connectby_tree 是表的名称。以“AS”开头的行是您命名列的方式。它看起来有点颠倒。

SELECT * FROM connectby('connectby_tree', 'keyid', 'parent_keyid', 'pos', 'row2', 0, '~')
    AS t(keyid text, parent_keyid text, level int, branch text, pos int);

【讨论】:

  • 如何向查询中添加更多列?假设,我还需要名字和姓氏。
【解决方案3】:

如 Stradas 所示,我报告了查询:

SELECT value 
FROM connectby('taxonomy', 'key', 'taxHier', '0', 0, '~') 
AS t(keyid numeric, parent_keyid numeric, level int, branch text) 
inner join taxonomy t on t.key = keyid;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-24
    • 1970-01-01
    • 2017-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多