web-dev-qa-db-fra.com

Quelle est la syntaxe PostgreSQL équivalente à CONNECT BY ... START WITH d'Oracle?

Dans Oracle, si j'ai une table définie comme…

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);

Avec ces valeurs…

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

Cette syntaxe de requête…

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

Donnera…

zero
one
four
two
five
six
three

Comment cela se fait-il dans PostgreSQL?

18
dacracot

Utiliser un RECURSIVE CTE dans Postgres:

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;

Détails et liens vers la documentation dans ma réponse précédente:

33
Erwin Brandstetter

Postgres a un équivalent de la connexion par. Vous devrez activer le module. Son désactivé par défaut.

Il est appelé tablefunc . Il prend en charge certaines fonctionnalités de tableau croisé ainsi que les familiers " se connectent par " et " Commencer par ". J'ai trouvé qu'il fonctionne beaucoup plus éloquemment et logiquement que le CTE récursif. Si vous ne pouvez pas activer cela avec votre DBA, vous devriez opter pour la façon dont Erwin le fait.
Il est suffisamment robuste pour effectuer également la requête de type "nomenclature".

Tablefunc peut être activé en exécutant cette commande:

CREATE EXTENSION tablefunc;

Voici la liste des champs de connexion fraîchement extraits de la documentation officielle.

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)

Vous devriez vraiment jeter un œil à la page des documents. Il est bien écrit et vous donnera les options auxquelles vous êtes habitué. (Sur la page doc, faites défiler vers le bas, c'est près du bas.)

Postgreql "Connect by" extension Ci-dessous est la description de ce que devrait être la mise en place de cette structure. Il y a une tonne de potentiel, donc je ne lui rendrai pas justice, mais en voici un extrait pour vous donner une idée.

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

Une vraie requête ressemblera à ceci. Connectby_tree est le nom de la table. La ligne commençant par "AS" est la façon dont vous nommez les colonnes. Cela semble un peu à l'envers.

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

Comme indiqué par Stradas, je signale la requête:

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;
0
sunrelax