PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

No psql como executar um Loop para uma consulta Select com CTEs e obter a saída mostrada se eu executá-lo em um banco de dados somente leitura?


Se eu decifrar isso direito, você basicamente quer selecionar todas as pessoas onde o número da linha de acordo com o ID descendente aparece no endereço. O resultado final deve ser limitado a alguns desses números de linha.

Então você não precisa usar esse incômodo LIMIT /OFFSET construir em tudo. Você pode simplesmente usar o row_number() função de janela.

Para filtrar os números das linhas, você pode simplesmente usar IN . Dependendo do que você quer aqui, você pode usar uma lista de literais, especialmente se os números não forem consecutivos. Ou você pode usar generate_series() para gerar uma lista de números consecutivos. Claro que você também pode usar uma subconsulta, quando os números são armazenados em outra tabela.

Com uma lista de literais que seria algo assim:
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);

Se você quiser usar generate_series() um exemplo seria:
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));
                             

E uma subconsulta de outra tabela poderia ser usada assim:
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 maiores de números, você também pode usar um INNER JOIN nos números em vez 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, '%');

Ou quando os números estão em outra tabela:
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, '%');

Observe que também alterei a correspondência de padrão de expressão regular para um simples LIKE . Isso tornaria as consultas um pouco mais portáteis. Mas é claro que você pode substituir isso por qualquer expressão que realmente precise.

db<>fiddle (com algumas das variantes)