简体   繁体   中英

How to create columns based on the value of one other column?

I have a table with accidents (~110,000 records) and a table with municipalities (~400 records). All accidents have a municipality code of the municipality where they occurred and I can count the number of accidents per municipality. For my project I need numbers / municipality.

One of the columns of the accidents table contains the type of object against which the accident occurred, eg car, truck, bicycle, etc. What I would like is to create new columns for each object type (car, truck, etc) with a count for each municipality.

Edit

Example of accidents table

mun_code objecttype
1        car
1        truck
1        car
2        bicycle
2        car
2        bicycle
2        truck
3        tree

Desired output

mun_code car truck bicycle tree
1        2   1     null    null
2        1   1     2       null
3        null null null    1

Instead of null, 0 is ok.

Edit 2

The point is that I have many columns that I have to aggregate over municipalities. I just wonder whether it is possible to have a script that automatically creates the needed columns for each objecttype and automatically aggregates for each objecttype

Is this possible to do in (postgres) SQL and how should I do this?

demo:db<>fiddle

Creating a pivot table can be achieved by using GROUP BY and FILTER clause

SELECT
    mun_code,
    COUNT(*) FILTER (WHERE object = 'car') as car,
    COUNT(*) FILTER (WHERE object = 'truck') as truck,
    COUNT(*) FILTER (WHERE object = 'bike') as bike,
    COUNT(*) FILTER (WHERE object = 'tree') as tree
FROM
    mytable
GROUP BY mun_code

If you really need NULL values instead of 0 , you can use the NULLIF() function afterwards

demo:db<>fiddle

NULLIF(COUNT(*) FILTER (WHERE object = 'car'), 0)

Edit: For dynamic numbers of columns, which is not simply achieveable, there is a small workaround using JSON:

demo:db<>fiddle

SELECT
    mun_code,
    jsonb_object_agg(object, count) AS jsonobject
FROM (
    SELECT
        mun_code,
        object,
        COUNT(*)
    FROM
        mytable t
    GROUP BY mun_code, object
) s
GROUP BY mun_code

With this, instead doing

SELECT car FROM my_pivoted_result

you can do:

SELECT jsonobject ->> 'car' FROM my_pivoted_result

you can use conditional aggregaiton

    select sum(case when type='car' then 1 else 0 end) as car,
    sum(case when type='truck' then 1 else 0 end) as truck,
    sum(case when type='bicycle' then 1 else 0 end) as bicycle

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