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。实际上,此方法可以利用每列上的单独索引。这意味着它可以优化到比我能想到的任何其他方法都要快。