从SQL Server中具有4列的表中的每个集合中获取前N行
假设我有一个包含4列的表:从SQL Server中具有4列的表中的每个集合中获取前N行,sql,sql-server,Sql,Sql Server,假设我有一个包含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
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脚本而不进行硬编码吗?方法1-用于MSSQL
方法3-用于MYSQL
替换tt.rank我认为下面的代码和预期的一样
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
对列使用group by子句,然后使用order by col3 desc获得所需的output4列,而不是字段。在我的问题中,SQL中的group by不适用,因为字段具有不同的值,当按列分组时,每个值都会转到自己的组,并且无法访问Top N col3@jarlh:ThanksThanks但Max返回Top Col3值但我希望按Col3排序时组的N个记录,示例中描述的是ThanksThanks,但条件是:当在多个具有Col1、Col2相等的记录中时,只导出该记录的Top N记录,该记录按Col3的降序排序,对不起,清楚吗?或者我必须描述更多?请注意这个问题,当Col1,Col2在多行中重复时,我的期望结果是Top N记录,COL3的顺序现在略有变化感谢您详细且经过测试的答案,这是非常好的答案
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
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
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
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;