2013-03-02 20 views
10

Używam PostgreSQL 9.1. W mojej bazie danych znajduje się tabela, która wygląda tak, jak:PostgreSQL unnest z pustą tablicą

id | ... | values 
----------------------- 
1 | ... | {1,2,3} 
2 | ... | {} 

gdzie id jest liczbą całkowitą, a wartości są liczbą całkowitą. Tablice mogą być puste.

Potrzebuję anulować tę listę. Jeśli kwerendy

select id, ..., unnest(values) 
from table 

mam trzy wiersze dla id = 1 (zgodnie z oczekiwaniami) i nie ma kolejek do id = 2. Czy istnieje sposób, aby uzyskać wynik jak

id | ... | unnest 
------------------- 
1 | ... | 1 
1 | ... | 2 
1 | ... | 3 
2 | ... | null 

czyli zapytania, które zawiera również linie, które mają pustą tablicę?

Odpowiedz

9
select id, 
     case 
     when int_values is null or array_length(int_values,1) is null then null 
     else unnest(int_values) 
     end as value 
from the_table; 

(zauważ, że zmieniono nazwę kolumny values do int_values jak values to słowo zarezerwowane i nie powinny być używane jako nazwy kolumny).

SQLFiddle: http://sqlfiddle.com/#!1/a0bb4/1


Postgres 10 nie pozwala używać unnest() takiego więcej.

Trzeba użyć boczny dołączyć:

select id, t.i 
from the_table 
    cross join lateral unnest(coalesce(nullif(int_values,'{}'),array[null::int])) as t(i); 

przykładem online: http://rextester.com/ALNX23313

+0

to nie działa na Postgresql 10 –

+0

@BleedingFingers: zobacz moją aktualizację –

0

Trzeba będzie użyć siebie LEFT JOIN, tak (także na SQL Fiddle):

SELECT t.id, u.u 
    FROM tab t 
    LEFT JOIN (SELECT id, unnest(vals) u FROM tab) u 
    USING (id); 

uwaga, że ​​dla większych tabel zapytań będzie wykonanie źle.

1
select id, 
    unnest (
     "values" 
     || 
     (array[null]::integer[])[1:(array_upper("values", 1) is null)::integer] 
    ) 
from "table" 
3

Na ponowne pytanie dotarło do mnie, że może to być prostsze i szybciej.
tyłu logikę currently accepted solution by @a_horse:

SELECT id, CASE WHEN values <> '{}' THEN unnest(values) END AS value 
FROM tbl 
  • Zwraca wiersz z NULL w value na pustą tablicę jak również dla NULL tablicy, ponieważ tylko tablicę z elementami produkuje TRUE w teście values <> '{}'.

  • Działa dla tablic o typie o dowolnym typie, ponieważ literał "{}" jest automatycznie wymuszany na pasujący typ.

  • Bez wyraźnego oddziału ELSE, CASE zwraca NULL, czego właśnie chcemy.

  • Tablice z elementami NULL będą zwracać wiersze niezależnie.
    Jednak. znalazłem anomalię i tam napisali pytanie o to:

    Okazało się, że to błąd, który został ustalony po moim raporcie za pg 9.3+.

Powiązane problemy