PostgreSQL unnest avec empty array

j'utilise postgreSQL 9.1. Dans ma base de données il y a une table qui ressemble à

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

où id est un entier et values est un tableau entier. Les tableaux peuvent être vides.

j'ai besoin de unnest cette liste. Si j'ai une requête

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

j'obtiens trois lignes pour id = 1 (comme prévu) et aucune ligne pour id = 2. Est-il possible d'obtenir un résultat semblable à

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

c'est à dire une requête qui contient également les lignes qui ont un tableau vide?

10
demandé sur rams 2013-03-02 17:48:46

5 réponses

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;

(notez que j'ai renommé la colonne valuesint_valuesvalues est un mot réservé et ne doit pas être utilisé comme un nom de colonne).

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


Postgres 10 ne permet pas d'utiliser unnest() comme ça, pas plus.

vous devez utiliser une jointure latérale:

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

exemple en ligne: http://rextester.com/ALNX23313


il peut être simplifié encore plus lorsqu'on utilise une jointure à gauche au lieu de la jointure en croix:

select id, t.i
from the_table
 left join lateral unnest(int_values) as t(i) on true;

exemple en ligne:http://rextester.com/VBO52351

11
répondu a_horse_with_no_name 2018-09-11 17:11:54

après avoir réexaminé cette question, je me suis dit que cela pouvait être plus simple et plus rapide.

Inverser la logique de l' solution actuellement acceptée par @a_horse:

SELECT id, CASE WHEN values <> '{}' THEN unnest(values) END AS value
FROM   tbl
  • renvoie une ligne avec NULLvalue pour un vide ainsi que NULL array, parce que seul un array avec des éléments produit TRUE dans le test values <> '{}'.

  • Fonctionne pour les tableaux de tapez, puisque le mot '{}' est automatiquement forcé à un type correspondant.

  • Sans explicite ELSE branche, CASE retourne NULL, ce que nous voulons de toute façon.

  • Tableaux NULL les éléments retourneront les lignes indépendamment.

    cependant. j'y ai trouvé une anomalie et posté une question concernant que:

    s'est avéré être un bug qui a été corrigé après mon rapport pour pg 9.3+.

3
répondu Erwin Brandstetter 2017-05-23 12:26:18
select id,
    unnest (
        "values"
        ||
        (array[null]::integer[])[1:(array_upper("values", 1) is null)::integer]
    )
from "table"
1
répondu Clodoaldo Neto 2013-03-02 15:31:35

Cela fonctionne sur Postgres 10 aussi:

SELECT id, UNNEST(CASE WHEN "values" <> '{}' THEN "values" ELSE '{null}' END)
1
répondu Eduardo 2018-04-09 15:37:00

Vous aurez besoin d'utiliser l'auto LEFT JOIN, comme ceci (également sur SQL Fiddle):

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

notez que pour les plus grandes tables, la requête va mal fonctionner.

0
répondu vyegorov 2013-03-02 14:18:04