问题
So i have a question for the tough hearted! I have had an issue with this concept for awhile and I need it to be cleared... The following code shows students who have more than 1 language
SELECT DISTINCT s.studentnumber as studentnr,
p.firstname AS name,
sl.gradenumber as gradenumber,
string_agg(DISTINCT l.text, ', ') as languages
FROM student s
JOIN pupil p ON p.id = s.pupilid
JOIN pupillanguage pl on pl.pupilid = p.id
JOIN language l on l.id = pl.languageid
JOIN schoollevel sl ON sl.id = p.schoollevelid
GROUP BY s.studentnumber,
p.firstname
Result
Now my question is simple yet I'm not sure how the answer would be... I want to split up those languages and put them in seperate fields so its looks something like this
Wanted Result
There is also 1 major issue. This is using Postgresql 9.3 which doesnt now allow grouping set or rollup or cube. I tried this code however and its not working correctly, im not sure how to deal with it and im not sure how to go forward about it...
(select distinct l.text
from language
join pupillanguage pl2 on pl2.languageid = language.id
join pupil on p.id = pl2.personid
limit 1) as language1
This is how the Tables looks like
Language Table
iD PK
shorttext char varying
text char varying
PupilLanguage Table
id PK
languageid FK
personid FK
displayorder int
回答1:
If you have a fixed number of columns, you can use an array:
select studentnr, name, gradenumber,
languages[1] as language_1,
languages[2] as language_2,
languages[3] as language_3,
languages[4] as language_4,
languages[5] as language_5
FROM (
SELECT s.studentnumber as studentnr,
p.firstname AS name,
sl.gradenumber as gradenumber,
array_agg(DISTINCT l.text) as languages
FROM student s
JOIN pupil p ON p.id = s.pupilid
JOIN pupillanguage pl on pl.pupilid = p.id
JOIN language l on l.id = pl.languageid
JOIN schoollevel sl ON sl.id = p.schoollevelid
GROUP BY s.studentnumber, p.firstname
) t
Note that distinct
is usually not needed when you use group by
回答2:
A SQL query returns a fixed number of columns. If you want just three additional columns, then you can use dynamic aggregation:
with t as (
SELECT s.studentnumber as studentnr, p.firstname AS name,
sl.gradenumber as gradenumber, l.text as language,
dense_rank() over (partition by s.studentnumber, p.firstname, sl.gradenumber order by l.text) as seqnum
FROM student s JOIN
pupil p
ON p.id = s.pupilid JOIN
pupillanguage pl
ON pl.pupilid = p.id JOIN
language l
ON l.id = pl.languageid JOIN
schoollevel sl
ON sl.id = p.schoollevelid
)
select studentnr, name, gradenumber,
max(case when seqnum = 1 then language end) as language_1,
max(case when seqnum = 2 then language end) as language_2,
max(case when seqnum = 3 then language end) as language_3
from t
group by studentnr, name, gradenumber;
However, if you want a variable number, then you need crosstab
or dynamic SQL. I might also suggest that you consider arrays instead.
来源:https://stackoverflow.com/questions/50581829/how-to-create-columns-for-different-fields-without-applying-the-pivoting-functio