问题
I need to create a table that is like the image below:
I can create the full 9 row table in sql using this code:
select a.start_year, a.start_month, b.start_year as order_year,
b.start_month as order_month
from list a
cross join list b;
How can I remove the unwanted rows, or just not create them in the first place?
回答1:
in ORACLE 11g
SELECT * FROM
(
SELECT y, x
FROM table_name
)
PIVOT
(
MAX(z)
FOR x IN (1, 2, 3)
)
ORDER BY y;
in SQL SERVER
SELECT [y], [1], [2], [3]
FROM [dbo].[table_name]
PIVOT
(
MAX(z)
FOR [x] IN ([1], [2], [3])
) AS P
in PostgreSQL
First compute the maximum value with the aggregate function max():
SELECT y, x, MAX(z)
FROM table_name
GROUP BY 1,2
ORDER BY 1,2
Then feed the result to the crosstab()
function as instructed in great detail in this related answer
Simple form - not fit for missing attributes
crosstab()
with one parameter:
SELECT *
FROM crosstab(
'SELECT x,y, z
FROM table_name
ORDER BY 1,2') -- needs to be "ORDER BY 1,2" here
AS ct ("X" text, "1" text, "2" text, "3" text);
Returns:
x | 1 | 2 | 3
--------+-----+-----+-----
A | a | b | c
B | d | e |
C | f | |
- No need for casting and renaming.
- Note the incorrect result for
C
the valuef
is filled in for the first column.
Safe form
crosstab()
with two parameters:
SELECT * FROM crosstab(
'SELECT x, y, z
FROM table_name
ORDER BY 1,2' -- could also just be "ORDER BY 1" here
,$$VALUES ('1'::text), ('2'), ('3')$$)
AS ct ("X" text, "1" text, "2" text, "3" text);
Returns:
x | 1 | 2 | 3
--------+-----+-----+-----
A | a | b | c
B | d | e |
C | | | f
Note the correct result for
C
.The second parameter can be any query that returns one row per attribute matching the order of the column definition at the end. Often you will want to query distinct attributes from the underlying table like this:
'SELECT DISTINCT attribute FROM table_name ORDER BY 1'
That's in the manual.
Since you have to spell out all columns in a column definition list anyway (except for pre-defined
crosstabN()
variants), it is regularly more efficient to provide a short list in aVALUES
expression like I demonstrate:$$VALUES ('1'::text), ('2'), ('3')$$)
Or:
$$SELECT unnest('{1,2,3}'::text[])$$ -- shorter for long lists
That's not in the manual.
I used dollar quoting to make quoting easier.
sqlpostgresqloraclesqlserver
来源:https://stackoverflow.com/questions/38365078/cohort-style-table-diagonal-grid-in-sql