J'ai un tableau d'éléments de texte, chaque élément de texte du tableau est une chaîne délimitée, voici un exemple :

drop table if exists tmp;
create table tmp(x text);
insert into tmp select ('1~41.5~50~1|2~43.72~1000~1|3~52.0~1~1|4~57.5~7500~1|5~68.0~8~1|6~80.95~6~1|7~84.25~300~1');

with t as (
    select string_to_array(x , '|') arr 
    from  tmp
)
select * , cardinality(arr) arr_len , split_part(arr[1],'~',2)
from t

Exemple de sortie:

"{1~41.5~50~1,2~43.72~1000~1,3~52.0~1~1,4~57.5~7500~1,5~68.0~8~1,6~80.95~6~1,7~84.25~300~1}";7;"41.5"

Je souhaite extraire le prix, qui est représenté comme le deuxième élément de chaque entrée de tableau (lorsqu'il est délimité par ~), de sorte que la sortie soit :

41.5,43.72,52.0,...

Lors de l'utilisation de split_part, qui ne renvoient qu'un seul résultat d'un index de tableau spécifique, et je ne veux pas coder en dur tous les index, car cela varie.

Les suggestions sont appréciées.

1
Y.S 8 sept. 2020 à 15:36

1 réponse

Meilleure réponse

Voici une approche:

select t.*, w.prices
from tmp t
cross join lateral (
    select array_agg(split_part(v.z, '~', 2)) prices
    from regexp_split_to_table(t.x, '\|') as v(z)
) w

Dans la sous-requête, nous divisons la chaîne en lignes, en utilisant le séparateur | ; puis, nous agrégeons le deuxième élément de chaque ligne dans un tableau.

Vous pouvez être explicite que vous souhaitez conserver l'ordre des éléments avec with ordinality :

select t.*, w.prices
from tmp t
cross join lateral (
    select array_agg(split_part(v.z, '~', 2) order by v.n) prices
    from regexp_split_to_table(t.x, '\|') with ordinality as v(z, n)
) w
1
GMB 8 sept. 2020 à 12:56