sql >> Base de Datos >  >> RDS >> PostgreSQL

En psql, ¿cómo ejecutar un bucle para una consulta de selección con CTE y obtener el resultado que se muestra si lo ejecuto en una base de datos de solo lectura?

Si descifro esto bien, básicamente quieres seleccionar a todas las personas donde aparece el número de fila según el ID descendente en la dirección. El resultado final debe limitarse a algunos de estos números de fila.

Entonces no necesitas usar ese engorroso LIMIT /OFFSET construir en absoluto. Simplemente puede usar el row_number() función de ventana.

Para filtrar los números de fila, simplemente puede usar IN . Dependiendo de lo que desee aquí, puede usar una lista de literales, especialmente si los números no son consecutivos. O puede usar generate_series() para generar una lista de números consecutivos. Por supuesto, también puede utilizar una subconsulta, cuando los números están almacenados en otra tabla.

Con una lista de literales que se verían así:

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 desea utilizar generate_series() un ejemplo sería:

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

Y una subconsulta de otra tabla podría usarse así:

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

Para conjuntos de números más grandes, también puede considerar usar un INNER JOIN en los números en lugar de IN .

Usando 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, '%');

O cuando los números están en otra tabla:

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, '%');

Tenga en cuenta que también cambié la coincidencia del patrón de expresión regular a un simple LIKE . Eso haría que las consultas fueran un poco más portátiles. Pero, por supuesto, puede reemplazar eso por cualquier expresión que realmente necesite.

db<>fiddle (con algunas de las variantes)