create table vote (Photo integer, Voter text, Decision text);
insert into vote values
(1, 'Alex', 'Cat'),
(1, 'Bob', 'Dog'),
(1, 'Carol', 'Cat'),
(1, 'Dave', 'Cat'),
(1, 'Ed', 'Cat'),
(2, 'Alex', 'Cat'),
(2, 'Bob', 'Dog'),
(2, 'Carol', 'Cat'),
(2, 'Dave', 'Cat'),
(2, 'Ed', 'Dog'),
(3, 'Alex', 'Horse'),
(3, 'Bob', 'Horse'),
(3, 'Carol', 'Dog'),
(3, 'Dave', 'Horse'),
(3, 'Ed', 'Horse'),
(4, 'Alex', 'Horse'),
(4, 'Bob', 'Horse'),
(4, 'Carol', 'Cat'),
(4, 'Dave', 'Horse'),
(4, 'Ed', 'Horse'),
(5, 'Alex', 'Dog'),
(5, 'Bob', 'Cat'),
(5, 'Carol', 'Cat'),
(5, 'Dave', 'Cat'),
(5, 'Ed', 'Cat')
;
La consulta para el gato:
select photo,
alex + bob + carol + dave + ed as Total,
alex, bob, carol, dave, ed
from crosstab($$
select
photo, voter,
case decision when 'Cat' then 1 else 0 end
from vote
order by photo
$$,'
select distinct voter
from vote
order by voter
'
) as (
photo integer,
Alex integer,
Bob integer,
Carol integer,
Dave integer,
Ed integer
);
photo | total | alex | bob | carol | dave | ed
-------+-------+------+-----+-------+------+----
1 | 4 | 1 | 0 | 1 | 1 | 1
2 | 3 | 1 | 0 | 1 | 1 | 0
3 | 0 | 0 | 0 | 0 | 0 | 0
4 | 1 | 0 | 0 | 1 | 0 | 0
5 | 4 | 0 | 1 | 1 | 1 | 1
Si el número de votantes es grande o no se conoce, se puede hacer de forma dinámica:
do $do$
declare
voter_list text;
r record;
begin
drop table if exists pivot;
voter_list := (
select string_agg(distinct voter, ' ' order by voter) from vote
);
execute(format('
create table pivot (
decision text,
photo integer,
Total integer,
%1$s
)', (replace(voter_list, ' ', ' integer, ') || ' integer')
));
for r in
select distinct decision from vote
loop
execute (format($f$
insert into pivot
select
%3$L as decision,
photo,
%1$s as Total,
%2$s
from crosstab($ct$
select
photo, voter,
case decision when %3$L then 1 else 0 end
from vote
order by photo
$ct$,$ct$
select distinct voter
from vote
order by voter
$ct$
) as (
photo integer,
%4$s
);$f$,
replace(voter_list, ' ', ' + '),
replace(voter_list, ' ', ', '),
r.decision,
replace(voter_list, ' ', ' integer, ') || ' integer'
));
end loop;
end; $do$;
El código anterior creó el pivote de la tabla con todas las decisiones:
select * from pivot where decision = 'Cat';