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

Junte 2 conjuntos com base na ordem padrão


Agora, para responder à pergunta real pergunta que foi revelada nos comentários, que parece ser algo como:

Existem algumas maneiras de lidar com isso:

  • Se e somente se as matrizes forem de tamanho igual, use vários unnest funções no SELECT cláusula (uma abordagem obsoleta que deve ser usada apenas para compatibilidade com versões anteriores);

  • Use generate_subscripts para fazer um loop sobre as matrizes;

  • Use generate_series sobre subconsultas em array_lower e array_upper para emular generate_subscripts se você precisar oferecer suporte a versões muito antigas para ter generate_subscripts;

  • Contando com a ordem que unnest retorna tuplas e espera - como na minha outra resposta e como mostrado abaixo. Vai funcionar, mas não é garantido que funcione em versões futuras.

  • Use o WITH ORDINALITY funcionalidade adicionada no PostgreSQL 9.4 (veja também sua primeira postagem ) para obter um número de linha para unnest quando 9,4 sai.

  • Use UNNEST de várias matrizes , que é o padrão SQL, mas que PostgreSQL ainda não suporta .

Então, digamos que temos a função arraypair com parâmetros de matriz a e b :
CREATE OR REPLACE FUNCTION arraypair (a integer[], b text[]) 
RETURNS TABLE (col_a integer, col_b text) AS $$
  -- blah code here blah
$$ LANGUAGE whatever IMMUTABLE;

e é invocado como:
SELECT * FROM arraypair( ARRAY[1,2,3,4,5,6,7], ARRAY['a','b','c','d','e','f','g'] );

possíveis definições de função seriam:

SRF-in-SELECT (obsoleto)

CREATE OR REPLACE FUNCTION arraypair (a integer[], b text[])
RETURNS TABLE (col_a integer, col_b text) AS $$
    SELECT unnest(a), unnest(b);
$$ LANGUAGE sql IMMUTABLE;

Produzirá resultados bizarros e inesperados se os arrays não forem iguais em comprimento; veja a documentação sobre funções de retorno de conjunto e seu uso não padrão no SELECT lista para saber por que e o que exatamente acontece.

generate_subscripts


Esta é provavelmente a opção mais segura:
CREATE OR REPLACE FUNCTION arraypair (a integer[], b text[])
RETURNS TABLE (col_a integer, col_b text) AS $$
    SELECT
       a[i], b[i]
    FROM generate_subscripts(CASE WHEN array_length(a,1) >= array_length(b,1) THEN a::text[] ELSE b::text[] END, 1) i;
$$ LANGUAGE sql IMMUTABLE;

Se os arrays forem de comprimento desigual, conforme escrito, ele retornará elementos nulos para o menor, então funciona como uma junção externa completa. Inverta o sentido da caixa para obter um efeito de junção interna. A função assume que os arrays são unidimensionais e que começam no índice 1. Se um argumento de array inteiro for NULL, a função retornará NULL.

Uma versão mais generalizada seria escrita em PL/PgSQL e verificaria array_ndims(a) = 1 , verifique array_lower(a, 1) = 1 , teste para matrizes nulas, etc. Vou deixar isso para você.

Esperando retornos em pares:


Não é garantido que isso funcione, mas funciona com o atual executor de consultas do PostgreSQL:
CREATE OR REPLACE FUNCTION arraypair (a integer[], b text[])
RETURNS TABLE (col_a integer, col_b text) AS $$
 WITH
    rn_c1(rn, col) AS (
      SELECT row_number() OVER (), c1.col
      FROM unnest(a) c1(col) 
    ),
    rn_c2(rn, col) AS (
      SELECT row_number() OVER (), c2.col
      FROM unnest(b) c2(col)
    )
    SELECT
      rn_c1.col AS c1, 
      rn_c2.col AS c2
    FROM rn_c1 
    INNER JOIN rn_c2 ON (rn_c1.rn = rn_c2.rn);
$$ LANGUAGE sql IMMUTABLE;

Eu consideraria usar generate_subscripts muito mais seguro.

Multi-argumento unnest :


Isso deve funciona, mas não porque o unnest do PostgreSQL não aceita vários arrays de entrada (ainda):
SELECT * FROM unnest(a,b);