Fusionner plusieurs lignes en une avec plus d'une valeur de ligne dans une colonne

Nov 19 2020

Je construis actuellement une requête pour récupérer des données de ma base de données, j'ai besoin d'accéder à certaines informations avec un identifiant commun sur une seule ligne.

Avec cette requête:

select 
        missions_answer.response_id as "response",
        crm_player."document" as "document",
        missions_question.label as "label",
        missions_answertext.body as "bill #",
        missions_answerselectmultiple.body as "product",
        missions_answerinteger.body as "answer" 
from missions_answer 
    left join missions_question on missions_answer.question_id = missions_question.id 
    left join missions_answertext on missions_answer.id = missions_answertext.answer_ptr_id 
    left join missions_answerselectmultiple on missions_answer.id = missions_answerselectmultiple.answer_ptr_id
    left join missions_answerinteger on missions_answer.id = missions_answerinteger.answer_ptr_id 
    left join missions_response on missions_answer.response_id = missions_response.id
    left join crm_player on missions_response.player_id = crm_player.id
    LEFT JOIN crm_user ON crm_player.user_id = crm_user.id
    where  missions_answer.response_id = '71788176'
    group by missions_answer.response_id, crm_player.document,missions_answertext.body,
        missions_question.label,
        missions_answerselectmultiple.body ,
        missions_answerinteger.body,
        crm_user.first_name,
        crm_user.last_name

Voici ce que j'ai actuellement:

+   response    +     document    +    label    +    bill #  +    product  +  answer
-   71788176    -     79907201    -    bill #   -    26899   -             -
-   71788176    -     79907201    -    amount   -            -             -    1
-   71788176    -     79907201    -    product  -      -    {"name": "Shoes"}   -
-   71788176    -     79907201    -    price    -            -             -  25.99

Voici ce que je recherche:

+   response    +     document    +    bill #  +    product  +  amount  +   price 
-   71788176    -     79907201    -    26899   -     shoes   -       1  -   25.99 

J'ai essayé de l'utiliser crosstabmais je ne parviens toujours pas à le trouver, merci d'avance pour toute indication ou aide.

Réponses

1 S-Man Nov 19 2020 at 09:31

À partir de votre état actuel, vous pouvez simplement faire le pivot en utilisant la FILTERclause:

démo: db <> fiddle

SELECT
    response,
    document,
    MAX(bill) FILTER (WHERE label = 'bill') as bill,
    MAX(answer) FILTER (WHERE label = 'amount') as amount,
    MAX(product) FILTER (WHERE label = 'product') as product,
    MAX(answer) FILTER (WHERE label = 'price') as price
FROM t
GROUP BY response, document

Je ne sais pas trop à quoi ressemble votre table d'origine. Si c'est plus comme ça:

response | document | label   | value
-------: | -------: | :------ | :----
71788176 | 79907201 | bill    | 26899
71788176 | 79907201 | amount  | 1    
71788176 | 79907201 | product | shoes
71788176 | 79907201 | price   | 25.99

Ensuite, vous pouvez modifier la requête comme ceci:

démo: db <> fiddle

SELECT
    response,
    document,
    MAX(value) FILTER (WHERE label = 'bill') as bill,
    MAX(value) FILTER (WHERE label = 'amount') as amount,
    MAX(value) FILTER (WHERE label = 'product') as product,
    MAX(value) FILTER (WHERE label = 'price') as price
FROM t
GROUP BY response, document

Edit : Pour ajouter la valeur JSON à la colonne de produit:

démo: db <> fiddle

Variante 1: vous pouvez simplement jsonconvertir le type en type text:

MAX(product::text) FILTER (WHERE label = 'product') as product,

Variante 2: vous lisez la valeur de l' "name"attribut:

MAX(product ->> 'name') FILTER (WHERE label = 'product') as product,