Sql 按组列出的多列中的前1个值

Sql 按组列出的多列中的前1个值,sql,sql-server,Sql,Sql Server,情况: +----+--------+-------+-------+-------+ | id | group | game1 | game2 | game3 | +----+--------+-------+-------+-------+ | 1 | brazil | wow | clash | dofus | | 1 | brazil | fifa | clash| dofus | | 1 | brazil | wow | wakfu | dofus |

情况:

+----+--------+-------+-------+-------+
| 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   |  
+----+--------+-------+-------+-------+
+--------+--------+-------+-------+
| 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')    
每个id都是一个组的一部分,这些id中有他们最喜欢的游戏

输出结构:

+----+--------+-------+-------+-------+
| 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   |  
+----+--------+-------+-------+-------+
+--------+--------+-------+-------+
| 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')    
目标:

+----+--------+-------+-------+-------+
| 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   |  
+----+--------+-------+-------+-------+
+--------+--------+-------+-------+
| 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')    
我需要按组计算game1、game2和game3的前1个值。排名前1的是在专栏中出现次数最多的游戏

结果应该是这样的:

+----+--------+-------+-------+-------+
| 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   |  
+----+--------+-------+-------+-------+
+--------+--------+-------+-------+
| 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')    
数据:

+----+--------+-------+-------+-------+
| 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   |  
+----+--------+-------+-------+-------+
+--------+--------+-------+-------+
| 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')    

使用一个
CTE
UNION
将所有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
请参阅。
结果:


使用一个
CTE
UNION
将所有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
请参阅。
结果:


我将建议
交叉应用

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;

我将建议
交叉应用

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;

首先,如果我的意见有任何意义,请重命名标题为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

所列示例:

首先,如果我的意见有任何意义,请重命名标题为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

所列示例:

您尝试过什么吗?您使用的是哪个版本的SQL Server?如果有相同数量的游戏,会发生什么情况?然后,您是在游戏描述中下单还是同时报告?您尝试过什么吗?您使用的是哪个版本的SQL Server?如果有相同数量的游戏,会发生什么情况?那么你是在游戏描述上下订单还是同时报告?我喜欢它的流线型,但在大量数据中交叉应用不会很慢吗?@TinyHaitian。实际上,此方法可以利用每列上的单独索引。这意味着它可以优化到比我能想到的任何其他方法都快。我喜欢它的流线型外观,但在大量数据中交叉应用不会很慢吗?@TinyHaitian。实际上,此方法可以利用每列上的单独索引。这意味着它可以优化到比我能想到的任何其他方法都要快。