简体   繁体   中英

Merge multiple rows into one with more than one row value in a column

I'm currently building a query to retrieve some data from my db, I need to access some information with a common id in just one row.

With this query:

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

This is what I currently have:

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

This is what I'm looking for:

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

I've been trying to use crosstab but I'm still unable to find it, thanks in advance for any hint or help.

From your current state you simply can do the pivot using the FILTER clause:

demo: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

I am not quite sure, how your original table looks like. If it is more like this:

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

Then you can modify the query like this:

demo: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 : TO added the JSON value to product column:

demo:db<>fiddle

Variant 1: You could simply cast the type json into type text :

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

Variant 2: You read the value from the "name" attribute:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM