PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Присъединете се към 2 комплекта въз основа на реда по подразбиране

Сега да отговоря на истинското въпрос, разкрит в коментарите, който изглежда нещо като:

Има няколко начина да се справите с това:

  • Ако и само ако масивите са с еднаква дължина, използвайте множество unnest функции в SELECT клауза (отхвърлен подход, който трябва да се използва само за обратна съвместимост);

  • Използвайте generate_subscripts за преминаване през масивите;

  • Използвайте generate_series над подзаявки срещу array_lower и array_upper за емулиране на generate_subscripts ако трябва да поддържате твърде стари версии, за да имате generate_subscripts;

  • Разчитайки на реда, който unnest връща кортежи и се надява - като в другия ми отговор и както е показано по-долу. Ще работи, но не е гарантирано, че ще работи в бъдещи версии.

  • Използвайте WITH ORDINALITY функционалност, добавена в PostgreSQL 9.4 (вижте също първата му публикация ), за да получите номер на ред за unnest когато излезе 9.4.

  • Използвайте множество масиви UNNEST , което е стандарт за SQL, но който PostgreSQL все още не се поддържа .

Да кажем, че имаме функция arraypair с параметри на масив a и 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;

и се извиква като:

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

възможните дефиниции на функции биха били:

SRF-in-SELECT (отхвърлено)

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;

Ще доведе до странни и неочаквани резултати, ако масивите не са еднакви по дължина; вижте документацията за връщащи набор функции и тяхната нестандартна употреба в SELECT списък, за да научите защо и какво точно се случва.

generate_subscripts

Това вероятно е най-безопасният вариант:

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;

Ако масивите са с различна дължина, както е написано, той ще върне нулеви елементи за по-късия, така че работи като пълно външно съединение. Обърнете смисъла на кутията, за да получите ефект, подобен на вътрешно съединение. Функцията приема, че масивите са едномерни и че започват от индекс 1. Ако целият аргумент на масива е NULL, тогава функцията връща NULL.

По-обобщена версия ще бъде написана на PL/PgSQL и ще проверява array_ndims(a) = 1 , проверете array_lower(a, 1) = 1 , тест за нулеви масиви и т.н. Ще оставя това на вас.

Надежда за възвращаемост по двойки:

Това не е гарантирано, че работи, но работи с текущия изпълнител на заявки на 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;

Бих обмислил използването на generate_subscripts много по-безопасно.

Множество аргументи unnest :

Това трябва работи, но не, защото unnest на PostgreSQL не приема множество входни масиви (все още):

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. 9.6 Най-страшният турнир

  2. Управление на замръзване в PostgreSQL

  3. Docker не разпознава директорията с данни на Postgresql

  4. Автоматично тестване на процеса на надстройка за PostgreSQL

  5. Postgresql заобикаля клеймото за време до най-близките 30 секунди