PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Dołącz 2 zestawy na podstawie domyślnej kolejności

Teraz, aby odpowiedzieć na prawdziwe pytanie, które zostało ujawnione w komentarzach, które wygląda na coś takiego:

Istnieje kilka sposobów rozwiązania tego problemu:

  • Jeśli i tylko wtedy, gdy tablice mają taką samą długość, użyj wielu unnest funkcje w SELECT klauzula (przestarzałe podejście, które powinno być używane tylko w celu zapewnienia zgodności z poprzednimi wersjami);

  • Użyj generate_subscripts zapętlić tablice;

  • Użyj generate_series nad podzapytaniami przeciwko array_lower i array_upper emulować generate_subscripts jeśli potrzebujesz obsługiwać wersje zbyt stare, aby mieć generate_subscripts;

  • Poleganie na kolejności, która unnest zwraca krotki i ma nadzieję - tak jak w mojej innej odpowiedzi i jak pokazano poniżej. Będzie działać, ale nie ma gwarancji, że będzie działać w przyszłych wersjach.

  • Użyj WITH ORDINALITY funkcjonalność dodana w PostgreSQL 9.4 (zobacz także jego pierwszy wpis ), aby uzyskać numer wiersza dla unnest gdy ukaże się wersja 9.4.

  • Użyj wielu tablic UNNEST , który jest standardem SQL, ale który PostgreSQL jeszcze nie obsługuje .

Powiedzmy, że mamy funkcję arraypair z parametrami tablicowymi a i 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;

i jest wywoływany jako:

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

możliwe definicje funkcji to:

SRF-in-SELECT (przestarzałe)

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;

Daje dziwne i nieoczekiwane wyniki, jeśli tablice nie są równej długości; zobacz dokumentację dotyczącą zestawu funkcji zwracających i ich niestandardowego użycia w SELECT listę, aby dowiedzieć się, dlaczego i co dokładnie się dzieje.

generate_subscripts

Jest to prawdopodobnie najbezpieczniejsza opcja:

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;

Jeśli tablice mają nierówną długość, tak jak napisano, zwróci ona elementy null dla krótszych, więc działa jak pełne sprzężenie zewnętrzne. Odwróć sens sprawy, aby uzyskać efekt połączenia wewnętrznego. Funkcja zakłada, że ​​tablice są jednowymiarowe i zaczynają się od indeksu 1. Jeśli cały argument tablicy ma wartość NULL, funkcja zwraca NULL.

Bardziej uogólniona wersja zostałaby napisana w PL/PgSQL i sprawdziłaby array_ndims(a) = 1 , sprawdź array_lower(a, 1) = 1 , przetestuj tablice null itp. Zostawię to Tobie.

Mam nadzieję na zwroty w parach:

Nie ma gwarancji, że to zadziała, ale działa z aktualnym executorem zapytań 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;

Rozważałbym użycie generate_subscripts znacznie bezpieczniejsze.

Wieloargumentowy unnest :

To powinno działa, ale nie działa, ponieważ unnest PostgreSQLa nie akceptuje wielu tablic wejściowych (jeszcze):

SELECT * FROM unnest(a,b);


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Najlepszy sposób na uzyskanie liczby wyników przed zastosowaniem LIMIT

  2. PostgreSQL przez poddźwiękowy

  3. Kompromisy we wdrożeniach w trybie gorącej gotowości

  4. Sekwencjonować i uwierzytelniać równorzędnie dla Postgresa?

  5. jak złapać błąd funkcji pg_connect()?