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

PostgreSQL unnest() с номер на елемент

Postgres 9.4 или по-нова версия

Използвайте WITH ORDINALITY за функции за връщане на набори:

Когато функция в FROM клаузата е суфиксирана от WITH ORDINALITY , abigint колона се добавя към изхода, който започва от 1 и се увеличава с 1 за всеки ред от изхода на функцията. Това е най-полезно в случай на функции за връщане на набор, като unnest() .

В комбинация с LATERAL функция в pg 9.3+ и според тази тема за pgsql-hackers, горната заявка вече може да бъде написана като:

SELECT t.id, a.elem, a.nr
FROM   tbl AS t
LEFT   JOIN LATERAL unnest(string_to_array(t.elements, ','))
                    WITH ORDINALITY AS a(elem, nr) ON TRUE;

LEFT JOIN ... ON TRUE запазва всички редове в лявата таблица, дори ако изразът на таблицата вдясно не връща редове. Ако това не ви притеснява, можете да използвате този иначе еквивалентен, по-малко подробен форма с имплицитно CROSS JOIN LATERAL :

SELECT t.id, a.elem, a.nr
FROM   tbl t, unnest(string_to_array(t.elements, ',')) WITH ORDINALITY a(elem, nr);

Или по-просто, ако се основава на действителен масив (arr като колона от масив):

SELECT t.id, a.elem, a.nr
FROM   tbl t, unnest(t.arr) WITH ORDINALITY a(elem, nr);

Или дори, с минимален синтаксис:

SELECT id, a, ordinality
FROM   tbl, unnest(arr) WITH ORDINALITY a;

a е автоматично таблица и псевдоним на колона. Името по подразбиране на добавената колона за ред е ordinality . Но е по-добре (по-безопасно, по-чисто) да добавите изрични псевдоними на колони и колони, отговарящи на изискванията за таблица.

Postgres 8.4 - 9.3

С row_number() OVER (PARTITION BY id ORDER BY elem) получавате числа според реда на сортиране, а не поредния номер на първоначалната редна позиция в низа.

Можете просто да пропуснете ORDER BY :

SELECT *, row_number() OVER (PARTITION by id) AS nr
FROM  (SELECT id, regexp_split_to_table(elements, ',') AS elem FROM tbl) t;

Въпреки че това обикновено работи и никога не съм го виждал да се проваля при прости заявки, PostgreSQL не твърди нищо относно реда на редовете без ORDER BY . Случва се да работи поради подробности за внедряването.

Загаранция на редни номера на елементи в разделения низ :

SELECT id, arr[nr] AS elem, nr
FROM  (
   SELECT *, generate_subscripts(arr, 1) AS nr
   FROM  (SELECT id, string_to_array(elements, ' ') AS arr FROM tbl) t
   ) sub;

Или по-просто, ако се основава на действителен масив :

SELECT id, arr[nr] AS elem, nr
FROM  (SELECT *, generate_subscripts(arr, 1) AS nr FROM tbl) t;

Свързан отговор на dba.SE:

  • Как да запазим оригиналния ред на елементите в невложен масив?

Postgres 8.1 - 8.4

Нито една от тези функции все още не е налична:RETURNS TABLE , generate_subscripts() , unnest() , array_length() . Но това работи:

CREATE FUNCTION f_unnest_ord(anyarray, OUT val anyelement, OUT ordinality integer)
  RETURNS SETOF record
  LANGUAGE sql IMMUTABLE AS
'SELECT $1[i], i - array_lower($1,1) + 1
 FROM   generate_series(array_lower($1,1), array_upper($1,1)) i';

Обърнете внимание по-специално, че индексът на масива може да се различава от редовите позиции на елементите. Помислете за тази демонстрация с разширена функция :

CREATE FUNCTION f_unnest_ord_idx(anyarray, OUT val anyelement, OUT ordinality int, OUT idx int)
  RETURNS SETOF record
  LANGUAGE sql IMMUTABLE AS
'SELECT $1[i], i - array_lower($1,1) + 1, i
 FROM   generate_series(array_lower($1,1), array_upper($1,1)) i';

SELECT id, arr, (rec).*
FROM  (
   SELECT *, f_unnest_ord_idx(arr) AS rec
   FROM  (VALUES (1, '{a,b,c}'::text[])  --  short for: '[1:3]={a,b,c}'
               , (2, '[5:7]={a,b,c}')
               , (3, '[-9:-7]={a,b,c}')
      ) t(id, arr)
   ) sub;

 id |       arr       | val | ordinality | idx
----+-----------------+-----+------------+-----
  1 | {a,b,c}         | a   |          1 |   1
  1 | {a,b,c}         | b   |          2 |   2
  1 | {a,b,c}         | c   |          3 |   3
  2 | [5:7]={a,b,c}   | a   |          1 |   5
  2 | [5:7]={a,b,c}   | b   |          2 |   6
  2 | [5:7]={a,b,c}   | c   |          3 |   7
  3 | [-9:-7]={a,b,c} | a   |          1 |  -9
  3 | [-9:-7]={a,b,c} | b   |          2 |  -8
  3 | [-9:-7]={a,b,c} | c   |          3 |  -7

Сравнете:

  • Нормализирайте индексите на масива за едномерен масив, така че да започват с 1


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да използвате модела за машинно обучение KNN с 2UDA – PostgreSQL и Orange (Част 1)

  2. PL/pgSQL проверка дали съществува ред

  3. Изпълнете роден sql с хибернация

  4. Създаване на настройка за репликация на PostgreSQL в Debian/Ubuntu

  5. PostgreSQL броят пъти, когато поднизът се появява в текста