从SQL Server中的4列表中获取每组中的前N行

问题描述 投票:1回答:3

假设我有一个包含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脚本执行此操作,无需硬编码吗?

sql sql-server
3个回答
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;

0
投票

我认为下面的代码是预期的

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

0
投票

方法1- FOR 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(2与您的N)

方法2-用于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-用于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将索引替换为2

© www.soinside.com 2019 - 2024. All rights reserved.