In short: I would like to use this input:
+---+---+---+
| x | y | z |
+---+---+---+
| 1 | 1 | a |
| 1 | 2 | b |
| 1 | 3 | c |
| 2 | 1 | d |
| 2 | 2 | e |
| 2 | 3 | f |
| 3 | 1 | g |
| 3 | 2 | h |
| 3 | 2 | i |
| . | . | . |
| n | . | .
+---+---+---+
to generate this output:
+---+---------+---------+---------+---------+
| y | z (x=1) | z (x=2) | z (x=3) | z (x=n) |
+---+---------+---------+---------+---------+
| 1 | a | d | g | . |
| 2 | b | e | h | . |
| 3 | c | f | i | . |
+---+---------+---------+---------+---------+
Table sample:
CREATE TABLE "public"."data" (
"x" text NOT NULL,
"y" text NOT NULL,
"z" text NOT NULL,
);
- The goal is to generate the output, in the most efficient way possible.
- max(x) will increase over time (->n)
- max(y) should remain constant but may increase by ~10%
- dynamic creation of z(x) columns & names
So far I have the following:
select * from crosstab('select y, x, z from data order by 1,2')
as ct (y varchar, x1z varchar, x2z varchar, x3z varchar,
x4z varchar, x5z varchar, x6z varchar)
;
which seems to work well (so far):
+----+-----+-----+-----+-----+-----+-----+
| y | x1z | x2z | x3z | x4z | x5z | x6z |
+----+-----+-----+-----+-----+-----+-----+
| 10 | fo | ob | ar | fo | ob | ar |
| 20 | ob | ar | fo | ob | ar | fo |
| 30 | ar | fo | ob | ar | fo | ob |
+----+-----+-----+-----+-----+-----+-----+
In the previous SQL snippet, I manually defined the static column names.
These should be based on x values & hence 'dynamic' matching below
select array (select distinct x from data order by x)
| x_campaigns |
| ------------------------- |
| ["1","2","3","4","5","6"] |
Another example to add clarity
- using the same crosstab SQL snippet, with arbitrarily defined column names
- these column names should be dynamically defined, in this example you can say: 'worldcup'+'year'
- in the previous case only 'x' is required, as is
CREATE TABLE world_cup(
year varchar(5),
game varchar(5),
score varchar(5))
;
-- insert values ...
select * from crosstab('select game, year, score from world_cup order by 1,2')
as ct (game varchar, WorldCup17 varchar, WorldCup18 varchar,
WorldCup19 varchar, WorldCup20 varchar, WorldCup21 varchar, WorldCup22 varchar)
+-------+------------+------------+------------+------------+------------+------------+
| match | worldcup17 | worldcup18 | worldcup19 | worldcup20 | worldcup21 | worldcup22 |
+-------+------------+------------+------------+------------+------------+------------+
| DE_FR | 2-2 | 1-1 | 0-0 | 3-2 | 0-2 | 1-2 |
| EN_DE | 2-0 | 0-2 | 2-1 | 0-0 | 3-0 | 0-0 |
| ES_FR | 0-1 | 0-0 | 1-5 | 0-5 | 1-1 | 3-1 |
+-------+------------+------------+------------+------------+------------+------------+
Thoughts?
Version: PostgreSQL 13.6 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit