Топ 1 значение из нескольких столбцов по группам - PullRequest
1 голос
/ 08 ноября 2019

Ситуация:

Каждый идентификатор является частью группы, и у этого идентификатора есть любимая игра.

Структура вывода:

+----+--------+-------+-------+-------+
| id | group  | game1 | game2 | game3 |  
+----+--------+-------+-------+-------+
|  1 | brazil | wow   | clash | dofus |  
|  1 | brazil | fifa  | clash| dofus |  
|  1 | brazil | wow   | wakfu | dofus |  
|  2 | korea  | clash | dofus | clash | 
|  2 | korea  | clash | dofus | clash |  
|  3 | france | wow   | fifa  | nfl   | 
|  3 | france | wow   | fifa  | nfl   |  
+----+--------+-------+-------+-------+

Цель:

Мне нужно взять верхнее значение 1 для game1, game2, game3 по группам. В верхней части 1 будет отображаться игра, которая чаще всего появляется в столбце.

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

+--------+--------+-------+-------+
| group  | game1  | game2 | game3 |
+--------+--------+-------+-------+
| brazil | wow    | clash | dofus |
| korea  | clash  | dofus | clash |
| france | wow    | fifa  | nfl   |
+--------+--------+-------+-------+

Данные:

create table #t1 (id int,[group] varchar(10),game1 varchar(10),game2 varchar(10),game3 varchar(10))

insert into #t1 values 
(1, 'brazil','wow','clash','dofus'),
(1, 'brazil','fifa','clash','dofus'),
(1, 'brazil','wow','wakfu','dofus'),
(2, 'korea','clash','dofus','clash'),
(2, 'korea','clash','dofus','clash'),
(3, 'france','wow','fifa','nfl'),
(3, 'france','wow','fifa','nfl')    

Ответы [ 3 ]

2 голосов
/ 08 ноября 2019

Я собираюсь предложить cross apply:

select t.group, g1.game1, g2.game2, g3.game3
from (select distinct group
      from #t1 t
     ) t cross apply
     (select top (1) game1
      from #t1 t
      group by game1
      order by count(*) desc
     ) g1 cross apply
     (select top (1) game2
      from #t1 t
      group by game2
      order by count(*) desc
     ) g2 cross apply
     (select top (1) game3
      from #t1 t
      group by game3
      order by count(*) desc
     ) g3;
1 голос
/ 08 ноября 2019

С CTE, который UNION s все 3 столбца в 1 столбец, а затем агрегировать по нему:

with cte as (
    select
      id, [group], gamecol, game, 
      row_number() over (partition by [group], gamecol order by count(*) desc) rn
    from (
      select id, [group], 'game1' gamecol, game1 game from #t1  
      union all
      select id, [group], 'game2', game2 from #t1
      union all
      select id, [group], 'game3', game3 from #t1
    ) t
    group by id, [group], gamecol, game
)
select
  id, [group], 
  max(case when gamecol = 'game1' then game end) game1,
  max(case when gamecol = 'game2' then game end) game2,
  max(case when gamecol = 'game3' then game end) game3
from cte
where rn = 1
group by id, [group]
order by id

См. Демонстрационную версию . Результаты:

> id | group  | game1 | game2 | game3
> -: | :----- | :---- | :---- | :----
>  1 | brazil | wow   | clash | dofus
>  2 | korea  | clash | dofus | clash
>  3 | france | wow   | fifa  | nfl  
0 голосов
/ 08 ноября 2019

Во-первых, если мое мнение что-то значит, переименуйте столбец с названием group . Хотя я полагаю, что вы могли набрать его для объяснения, это может привести к ошибке, поскольку она зарезервирована (или нет, если используются скобки). Во всяком случае, было бы легче читать.

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

    ;WITH Set1 AS
    (
        SELECT id, GameGroup, game1, 
        ROW_NUMBER() OVER (PARTITION BY [id] ORDER BY id ASC, count(game1) DESC) rn
        FROM #t1
        GROUP BY id, GameGroup, game1
    ), 
    Set2 AS
    (
        SELECT id, GameGroup, game2, 
        ROW_NUMBER() OVER (PARTITION BY [id] ORDER BY id ASC, count(game2) DESC) rn
        FROM #t1
        GROUP BY id, GameGroup, game2
    ),
    Set3 AS
    (
        SELECT id, GameGroup, game3, 
        ROW_NUMBER() OVER (PARTITION BY [id] ORDER BY id ASC, count(game3) DESC) rn
        FROM #t1
        GROUP BY id, GameGroup, game3
    )

    SELECT a.GameGroup, a.game1, b.game2, c.game3
    FROM Set1 a
    INNER JOIN Set2 b
      ON a.id = b. id AND a.rn = b.rn
    INNER JOIN Set3 c
      ON a.id = c.id AND a.rn = c.rn
    WHERE a.rn = 1

Пример в списке здесь :

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...