从 SQL Server 中 4 列的表中获取每组的前 N 行
Posted
技术标签:
【中文标题】从 SQL Server 中 4 列的表中获取每组的前 N 行【英文标题】:Get Top N row from each set from table with 4 column in SQL Server 【发布时间】:2017-12-18 10:39:36 【问题描述】:假设我有一个有 4 列的表:
Col1 Col2 Col3 Col4
我的初始查询是:
SELECT Col1, Col2, Col3, Col4
FROM myTable
ORDER BY Col1, Col2, Col3 DESC, Col4
我想要的结果是所有 4 列,但是在这种情况下,当 Col1、Col2 相等时,Top N Col3 不同的行。
N=2 的示例:
表格样本数据:
Col1 Col2 Col3 Col4
---------------------
1 a 2000 s
1 a 2002 c
1 a 2001 b
2 b 1998 s
2 b 2002 c
2 b 2000 b
3 c 2000 b
1 f 1998 n
1 g 1999 e
想要的结果:
1 a 2002 c
1 a 2001 b
1 f 1998 n
1 g 1999 e
2 b 2002 c
2 b 2000 b
3 c 2000 b
另外一种描述,当(col1, col2)
在多条记录中重复出现时,按照Col3降序排列,只导出这些记录的前N行。
我可以用 SQL 脚本做到这一点,而不用硬编码吗?
【问题讨论】:
对列使用 group by 子句,然后使用 order by col3 desc 得到我们想要的输出 4 个列,而不是字段。 group by in SQL in my question不适合,因为字段有不同的值,当按列分组时,每个值都属于自己的组,无法访问前 N Col3! @jarlh:谢谢 【参考方案1】:declare @t table (Col1 int, Col2 char, Col3 int, Col4 char);
insert into @t values
(1, 'a', 2000, 's'),
(1, 'a', 2002, 'c'),
(1, 'a', 2001, 'b'),
(2, 'b', 1998, 's'),
(2, 'b', 2002, 'c'),
(2, 'b', 2000, 'b'),
(3, 'c', 2000, 'b'),
(1, 'f', 1998, 'n'),
(1, 'g', 1999, 'e');
declare @N int = 2; -- number per "top"
with cte as
(
select *,
row_number() over(partition by col1, col2 order by col3 desc) as rn
from @t
)
select *
from cte c
where rn <= @N;
【讨论】:
感谢您提供详细且经过测试的答案,这个答案非常好【参考方案2】:我认为下面的代码符合预期
declare @tab table (Col1 int, Col2 char(1), Col3 int, Col4 char(1))
declare @N int
insert into @tab
select 1, 'a' , 2000, 's'
union all
select 1 , 'a' , 2002 , 'c'
union all
select 1 , 'a' , 2001 , 'b'
union all
select 2 , 'b' , 1998 , 's'
union all
select 2 , 'b' , 2002 ,'c'
union all
select 2 , 'b' , 2000 ,'b'
union all
select 3 , 'c' , 2000 ,'b'
union all
select 1 , 'f' , 1998 ,'n'
union all
select 1 , 'g' , 1999 ,'e'
;with tab as
(
select ROW_NUMBER() over(partition by t.col1,t.col2 order by t.col3 desc) as row,t.*
from @tab t
)
select Col1,Col2,Col3,Col4
from tab
where row < 3
输出
Col1 Col2 Col3 Col4
1 a 2002 c
1 a 2001 b
1 f 1998 n
1 g 1999 e
2 b 2002 c
2 b 2000 b
3 c 2000 b
【讨论】:
谢谢,但 Max 返回 Top Col3 值但我希望在示例中描述的 Col3 订购时有 N 组记录 谢谢,但条件是:当在具有 (Col1,Col2) Equal 的多个记录中,只需导出此记录的 Top N 记录,即按 Col3 降序排序,对不起,很清楚,或者我必须描述更多?【参考方案3】:方法 1- 适用于 MSSQL
http://sqlfiddle.com/#!6/4bda39/6
with a as (
select ROW_NUMBER() over(partition by t.col1,t.col2 order by t.col3 desc) as row,t.*
from myTable as t)
select * from a where a.row <= 2
替换 a.row (2 用你的 N)
方法 2- FOR MYSQL
http://sqlfiddle.com/#!9/79e81a/63
SELECT myTable.Col1, myTable.Col2, myTable.Col3, myTable.Col4
FROM (
Select Col1 as Col1, Col2 as Col2, count(Col1) as cc, AVG(Col3) as aa
From myTable
group by Col1, Col2) as tt
join myTable on myTable.Col1 = tt.Col1 and myTable.Col2 = tt.Col2
where myTable.Col3 >= tt.aa
Order by Col1 ,Col2 ,Col3 Desc,Col4
方法 3- FOR MYSQL
http://sqlfiddle.com/#!9/79e81a/79
SELECT * FROM (
SELECT CASE Col1
WHEN @Col1 THEN
CASE Col2
WHEN @Col2 THEN @curRow := @curRow + 1
ELSE @curRow := 1
END
ELSE @curRow :=1
END AS rank,
@Col1 := Col1 AS Col1,
@Col2 := Col2 AS Col2,
Col3, Col4
FROM myTable p
JOIN (SELECT @curRow := 0, @Col1 := 0, @Col2 := '') r
ORDER BY Col1, Col2, Col3 DESC) as tt
WHERE tt.rank <= 2
替换 tt.rank 将 2 替换为您想要的索引
【讨论】:
请注意问题,当 (Col1 , Col2 ) 在多行重复时,我想要的结果是 Top N Record that order by Col3 现在做了一些小改动以上是关于从 SQL Server 中 4 列的表中获取每组的前 N 行的主要内容,如果未能解决你的问题,请参考以下文章
sql server 查询 order by 与 union 并替换多个列的空值
如何从 SQL Server 中特定数据库的表中获取所有列名?