PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Dans psql, comment exécuter une boucle pour une requête Select avec des CTE et obtenir la sortie affichée si je l'exécute dans une base de données en lecture seule ?

Si je déchiffre ce droit, vous voulez essentiellement sélectionner toutes les personnes où le numéro de ligne selon l'ID décroissant apparaît dans l'adresse. Le résultat final devrait alors être limité à certains de ces numéros de ligne.

Ensuite, vous n'avez pas besoin d'utiliser cette lourde LIMIT /OFFSET construire du tout. Vous pouvez simplement utiliser le row_number() fonction fenêtre.

Pour filtrer les numéros de ligne, vous pouvez simplement utiliser IN . Selon ce que vous voulez ici, vous pouvez soit utiliser une liste de littéraux, surtout si les nombres ne sont pas consécutifs. Ou vous pouvez utiliser generate_series() pour générer une liste de numéros consécutifs. Bien sûr, vous pouvez également utiliser une sous-requête, lorsque les nombres sont stockés dans une autre table.

Avec une liste de littéraux qui ressemblerait à ceci :

SELECT pn.personid,
       pn.lastname,
       pn.firstname,
       pn.address,
       pn.city
       FROM (SELECT p.personid,
                    p.lastname,
                    p.firstname,
                    p.address,
                    p.city,
                    row_number() OVER (ORDER BY p.personid DESC) n
                    FROM persons p) pn
       WHERE pn.address LIKE concat('%', pn.n, '%')
             AND pn.n IN (1, 2, 4);

Si vous souhaitez utiliser generate_series() un exemple serait :

SELECT pn.personid,
       pn.lastname,
       pn.firstname,
       pn.address,
       pn.city
       FROM (SELECT p.personid,
                    p.lastname,
                    p.firstname,
                    p.address,
                    p.city,
                    row_number() OVER (ORDER BY p.personid DESC) n
                    FROM persons p) pn
       WHERE pn.address LIKE concat('%', pn.n, '%')
             AND pn.n IN (SELECT s.n
                                 FROM generate_series(1, 3) s (n));
                             

Et une sous-requête d'une autre table pourrait être utilisée comme ceci :

SELECT pn.personid,
       pn.lastname,
       pn.firstname,
       pn.address,
       pn.city
       FROM (SELECT p.personid,
                    p.lastname,
                    p.firstname,
                    p.address,
                    p.city,
                    row_number() OVER (ORDER BY p.personid DESC) n
                    FROM persons p) pn
       WHERE pn.address LIKE concat('%', pn.n, '%')
             AND pn.n IN (SELECT t.nmuloc
                                 FROM elbat t);

Pour de plus grands ensembles de nombres, vous pouvez également envisager d'utiliser un INNER JOIN sur les chiffres au lieu de IN .

Utilisation de generate_series() :

SELECT pn.personid,
       pn.lastname,
       pn.firstname,
       pn.address,
       pn.city
       FROM (SELECT p.personid,
                    p.lastname,
                    p.firstname,
                    p.address,
                    p.city,
                    row_number() OVER (ORDER BY p.personid DESC) n
                    FROM persons p) pn
            INNER JOIN generate_series(1, 1000000) s (n)
                       ON s.n = pn.n
       WHERE pn.address LIKE concat('%', pn.n, '%');

Ou lorsque les nombres sont dans une autre table :

SELECT pn.personid,
       pn.lastname,
       pn.firstname,
       pn.address,
       pn.city
       FROM (SELECT p.personid,
                    p.lastname,
                    p.firstname,
                    p.address,
                    p.city,
                    row_number() OVER (ORDER BY p.personid DESC) n
                    FROM persons p) pn
            INNER JOIN elbat t
                       ON t.nmuloc = pn.n
       WHERE pn.address LIKE concat('%', pn.n, '%');

Notez que j'ai également changé le modèle d'expression régulière correspondant à un simple LIKE . Cela rendrait les requêtes un peu plus portables. Mais vous pouvez bien sûr remplacer cela par n'importe quelle expression dont vous avez vraiment besoin.

db<>violon (avec certaines variantes)