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

Únete a 2 conjuntos según el orden predeterminado

Ahora, para responder a la real pregunta que se reveló en los comentarios, que parece ser algo como:

Hay un par de maneras de abordar esto:

  • Si y solo si las matrices tienen la misma longitud, use múltiples unnest funciones en el SELECT cláusula (un enfoque obsoleto que solo debe usarse para la compatibilidad con versiones anteriores);

  • Utilice generate_subscripts para recorrer las matrices;

  • Usa generate_series sobre subconsultas contra array_lower y array_upper para emular generate_subscripts si necesita admitir versiones demasiado antiguas para tener generate_subscripts;

  • Confiando en el orden que unnest devuelve tuplas y espera, como en mi otra respuesta y como se muestra a continuación. Funcionará, pero no se garantiza que funcione en futuras versiones.

  • Usa el WITH ORDINALITY funcionalidad añadida en PostgreSQL 9.4 (ver también su primera publicación ) para obtener un número de fila para unnest cuando sale 9.4.

  • Usar matriz múltiple UNNEST , que es estándar SQL pero que PostgreSQL no es compatible todavía .

Entonces, digamos que tenemos la función arraypair con parámetros de matriz a y 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;

y se invoca como:

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

posibles definiciones de función serían:

SRF-en-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;

Producirá resultados extraños e inesperados si las matrices no tienen la misma longitud; consulte la documentación sobre las funciones de devolución de conjuntos y su uso no estándar en SELECT lista para saber por qué y qué sucede exactamente.

generate_subscripts

Esta es probablemente la opción más 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;

Si las matrices tienen una longitud desigual, como está escrito, devolverá elementos nulos para el más corto, por lo que funciona como una combinación externa completa. Invierta el sentido del caso para obtener un efecto similar al de unión interna. La función asume que las matrices son unidimensionales y que comienzan en el índice 1. Si el argumento de una matriz completa es NULL, la función devuelve NULL.

Una versión más generalizada estaría escrita en PL/PgSQL y verificaría array_ndims(a) = 1 , marque array_lower(a, 1) = 1 , probar matrices nulas, etc. Te lo dejo a ti.

Esperando retornos por parejas:

No se garantiza que funcione, pero funciona con el ejecutor de consultas actual de 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;

Consideraría usar generate_subscripts mucho más seguro.

Multi-argumento unnest :

Esto debería funciona, pero no porque unnest de PostgreSQL no acepta múltiples matrices de entrada (todavía):

SELECT * FROM unnest(a,b);