Postgres 9.4 veya üstü
WITH ORDINALITY
Küme geri dönüş işlevleri için kullanın :
FROM
Cümlede bir işlevin sonuna eklendiğinde, çıktıya 1'den başlayan ve işlevin çıktısının her satırı için 1 artan WITH ORDINALITY
bir
bigint
sütun eklenir. Bu, en çok gibi küme döndürme işlevlerinde yararlıdır unnest()
.
LATERAL
9.3+ sayfasındaki özellik ile birlikte ve pgsql-hacker'lardaki bu konuya göre , yukarıdaki sorgu artık şu şekilde yazılabilir:
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
Sağdaki tablo ifadesi hiç satır döndürmese bile soldaki tablodaki tüm satırları korur. Bu endişe verici değilse, aksi takdirde eşdeğer olan, daha az ayrıntılı formu örtük bir şekilde kullanabilirsiniz CROSS JOIN LATERAL
:
SELECT t.id, a.elem, a.nr
FROM tbl t, unnest(string_to_array(t.elements, ',')) WITH ORDINALITY a(elem, nr);
Veya gerçek bir diziye dayalıysa ( arr
bir dizi sütunu ise) daha basittir :
SELECT t.id, a.elem, a.nr
FROM tbl t, unnest(t.arr) WITH ORDINALITY a(elem, nr);
Veya minimum sözdizimiyle:
SELECT id, a, ordinality
FROM tbl, unnest(arr) WITH ORDINALITY a;
a
otomatik olarak tablo ve sütun takma adıdır. Eklenen sıra sütununun varsayılan adı ordinality
. Ancak, açık sütun takma adları ve tabloya uygun sütunlar eklemek daha iyidir (daha güvenli, daha temiz).
Postgres 8.4 - 9.3
İle , dizedeki orijinal sıra konumununrow_number() OVER (PARTITION BY id ORDER BY elem)
sıra sayısına göre değil, sıralama düzenine göre sayılar alırsınız .
Basitçe atlayabilirsiniz ORDER BY
:
SELECT *, row_number() OVER (PARTITION by id) AS nr
FROM (SELECT id, regexp_split_to_table(elements, ',') AS elem FROM tbl) t;
Bu normalde işe yarasa ve basit sorgularda başarısız olduğunu hiç görmedim, PostgreSQL satırların sırasına ilişkin hiçbir şey öne sürmez. ORDER BY
. Bir uygulama detayı nedeniyle işe yarıyor.
Boşluklarla ayrılmış dizede sıra sayılarını garanti etmek için :
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;
Veya gerçek bir diziye dayalıysa daha basit :
SELECT id, arr[nr] AS elem, nr
FROM (SELECT *, generate_subscripts(arr, 1) AS nr FROM tbl) t;
Dba.SE ile ilgili cevap:
Postgres 8.1 - 8.4
Bu özelliklerin hiçbiri henüz kullanılabilir: RETURNS TABLE
, generate_subscripts()
, unnest()
, array_length()
. Ancak bu işe yarar:
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';
Özellikle, dizi indeksinin öğelerin sıra konumlarından farklı olabileceğini unutmayın. Bu demoyu genişletilmiş bir işlevle düşünün :
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[])
, (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
Karşılaştırmak: