Функция агрегирования сводной таблицы MS SQL SERVER - PullRequest
0 голосов
/ 07 июня 2018

У меня есть вопрос о применении функции агрегирования, которая использовалась в сводной функции.

Таблица OCCUPATIONS выглядит следующим образом:

+-----------+------------+
|   Name    | Occupation |
+-----------+------------+
| Ashley    | Professor  |
| Samantha  | Actor      |
| Julia     | Doctor     |
| Britney   | Professor  |
| Maria     | Professor  |
| Meera     | Professor  |
| Priya     | Doctor     |
| Priyanka  | Professor  |
| Jennifer  | Actor      |
| Ketty     | Actor      |
| Belvet    | Professor  |
| Naomi     | Professor  |
| Jane      | Singer     |
| Jenny     | Singer     |
| Kristeen  | Singer     |
| Christeen | Singer     |
| Eve       | Actor      |
| Aamina    | Doctor     |
+-----------+------------+

Первый столбец - имя, а второй -занятие.Теперь я хочу создать сводную таблицу, в которой каждый столбец представляет собой один вид занятия, а имя отсортировано в алфавитном порядке, и выведите NULL, когда больше нет имен для занятия.

Вывод должен выглядеть следующим образом:

+--------+-----------+-----------+----------+
| Doctor | Professor |  Singer   |  Actor   |
+--------+-----------+-----------+----------+
| Aamina | Ashley    | Christeen | Eve      |
| Julia  | Belvet    | Jane      | Jennifer |
| Priya  | Britney   | Jenny     | Ketty    |
| NULL   | Maria     | Kristeen  | Samantha |
| NULL   | Meera     | NULL      | NULL     |
| NULL   | Naomi     | NULL      | NULL     |
| NULL   | Priyanka  | NULL      | NULL     |
+--------+-----------+-----------+----------+

Здесь первая колонка «Доктор», вторая - «Профессор», третья - «Сингер» и четвертая - «Актер».Код для генерации результата:

select [Doctor],[Professor],[Singer],[Actor] from (select o.Name, 
o.Occupation, row_number() over(partition by o.Occupation order by 
o.Name) id from OCCUPATIONS o) as src
pivot
(max(src.Name)
for src.Occupation in ([Doctor],[Professor],[Singer],[Actor])
) as m

Но когда я заменяю сгенерированную здесь таблицу:

(select o.Name, o.Occupation, row_number() over(partition by o.Occupation order by o.Name) id from OCCUPATIONS o) as src' to 'OCCUPATIONS'

результат выглядит так:

Priya Priyanka Kristeen Samantha 

Iпонять, почему это происходит, потому что мы берем MAX() в каждой группе.Тем не менее, в предыдущем результате я также использую функцию MAX() для генерации NULL, когда больше не будет названий, оно не возвращает максимальное значение, как ожидалось, вместо этого оно возвращает каждое имя.

Мой вопрос, почему это происходит?

Спасибо!

Ответы [ 3 ]

0 голосов
/ 23 июня 2018

Попробуйте этот подход:

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

Это запрос:

declare @tmp table([Name] varchar(50),[Occupation] varchar(50))
insert into @tmp values
 ('Ashley','Professor') ,('Samantha','Actor') ,('Julia','Doctor') ,('Britney','Professor') ,('Maria','Professor') ,('Meera','Professor') ,('Priya','Doctor') ,('Priyanka','Professor') ,('Jennifer','Actor') ,('Ketty','Actor') ,('Belvet','Professor') ,('Naomi','Professor') ,('Jane','Singer') ,('Jenny','Singer') ,('Kristeen','Singer') ,('Christeen','Singer') ,('Eve','Actor') ,('Aamina','Doctor')

--this variable contains the occuation that has more Names (rows) in the table
--it will be the number of total rows in output table
declare @Occupation_with_max_rows varchar(50)

--populate @Occupation_with_max_rows variable
select top 1 @Occupation_with_max_rows=Occupation 
from @tmp
group by Occupation 
order by count(*) desc

--generate final results joining 4 times the original table with the sequence table 
select D.Name as Doctor,P.Name as Professor,S.Name as Singer,A.Name as Actor 
from 
(select ROW_NUMBER() OVER (ORDER BY [Name]) as ord from @tmp where Occupation = @Occupation_with_max_rows) O
left  join
(select ROW_NUMBER() OVER (ORDER BY [Name]) as ord, [Name] from @tmp where Occupation='Doctor') D on O.ord = D.ord
left  join
(select ROW_NUMBER() OVER (ORDER BY [Name]) as ord, [Name] from @tmp where Occupation='Professor') P on O.ord = P.ord
left join
(select ROW_NUMBER() OVER (ORDER BY [Name]) as ord, [Name] from @tmp where Occupation='Singer') S on O.ord = S.ord
left join
(select ROW_NUMBER() OVER (ORDER BY [Name]) as ord, [Name] from @tmp where Occupation='Actor') A on O.ord = A.ord

Результаты:

enter image description here

0 голосов
/ 31 июля 2019

Пожалуйста, найдите ниже код, который работает как ожидалось:

select [Doctor],[Professor],[Singer],[Actor]
      from 
(
  select row_number() over (partition by occupation order by name)[A],name,occupation  
   from occupations
 )src
pivot
(
 max(Name)
 for occupation in ([Doctor],[Professor],[Singer],[Actor])
 )piv;
0 голосов
/ 08 июня 2018

Здесь может быть источник проблемы:

row_number() over(partition by o.Occupation order by 
o.Name) id from OCCUPATIONS o

Row_Number, который вы здесь используете, равен PARTITION BY o.Occupation, поэтому в вашем PIVOT он будет поворачивать записи по группе занятий,что означает, что id повторяется.Если вы избавитесь от PARTITION BY и просто сохраните часть Order by, она должна работать.

...