Часть 2: как получить сумму запроса на основе разделов без фактического поворота - PullRequest
0 голосов
/ 30 мая 2018

, так как у меня нет последней версии Postgresql (у меня есть Postgresql 9.3), я не смог придумать функцию, аналогичную функции pivot, которая вычисляет общее значение частичного поля.

Вы можете щелкнуть ссылку ниже, чтобы использовать вопрос, который я создал в качестве ссылки, они похожи по коду, но отличаются в аспекте требований, но есть второй запрос, который использует массив и также дает точно такие же результаты.

Как создавать столбцы для разных полей без применения функции поворота

В настоящее время я получаю следующие результаты

Current output

Я хочу эти результаты

enter image description here

Ниже у меня естьзапрос , который возвращает мне языки, на которых говорят студенты, в 3 разных столбцах ... Моя проблема в том, что я не могу найти решение, которое может вернуть мне сумму, сколько студентов говорят на 1 языке1, сколько говорят на языке2сколько людей говорят на языке3

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;

Я задаю этот вопрос, потому что, если нет способа сделать это, мне не нужно вдаваться в подробности, если это невозможно.

Вся эта концепция разделения и диплэнка является относительно новой для меня, и я не уверен в их масштабах и возможностях для получения дальнейших результатов.

1 Ответ

0 голосов
/ 30 мая 2018

Используйте решение, которое у вас есть (либо одно, я предпочитаю решение с массивами по понятным причинам), поместите его в CTE, а затем используйте UNION для вычисления итогов:

with students as (
  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
)
select *
from students
union all
select null as studentnr,
       null as name, 
       null as gradenumber, 
       count(language_1)::text,
       count(language_2)::text, 
       count(language_3)::text, 
       count(language_4)::text, 
       count(language_5)::text
from students;

Агрегируйте такие функции, как count() игнорировать NULL значения, поэтому он будет считать только те строки, где существует язык.

Типы данных всех столбцов в запросах UNION должны совпадать, поэтому вы не можете возвращать целочисленные значения в столбце во втором запросе, если первый запрос определяет этот столбец как текст (или varchar),Вот почему результат count() должен быть приведен к text

Псевдонимы столбцов во втором запросе на самом деле не нужны, но я добавил их, чтобы показать, как должны совпадать списки столбцов.

...