简体   繁体   English

通过SQL选择TOP 2 MAX值组

[英]SELECT TOP 2 MAX Value Group By SQL

I have the following table: 我有下表:

-----------------------------------------
xDate        xItem       xCount
-----------------------------------------
2018-01-01   A           100
2018-01-01   B           200
2018-01-01   D           500
2018-01-02   C           200
2018-01-02   E           800

I want to select TOP 2 value for each date on the MAX value of xCount field. 我想在xCount字段的MAX值上为每个日期选择TOP 2值。 So, the result should be: 因此,结果应为:

-----------------------------------------
xDate        xItem      xCount
-----------------------------------------
2018-01-01   D          500
2018-01-01   B          200
2018-01-02   E          800
2018-01-02   C          200

Does anyone have an idea for this case? 有人对此案有想法吗?
Cheers, 干杯,

You can try to use RANK window function, if there more the two row have same xCount then you want to get them all. 您可以尝试使用RANK窗口函数,如果两行中的xCount相同,则您希望全部获取它们。

You can try to use dense_rank instead of RANK 您可以尝试使用dense_rank而不是RANK

SELECT xDate,xItem,xCount
FROM (
    SELECT *,RANK() OVER(PARTITION BY xDate ORDER BY xCount DESC) rn
    FROM T
) t1
WHERE t1.rn <= 2

You can use ROW_NUMBER() and partition it on the basis of xDate and order by xCount to get what you want. 您可以使用ROW_NUMBER()并根据xDate对其进行分区, xDate进行xCount以获取所需的内容。

select X.xDate, 
       X.xItem, 
       X.xCount
  from 
       (select xDate, 
               xItem, 
               xCount, 
               row_number() over (partition by xDate order by xCount desc) rank_of_count
         from table_name) X
 where rank_of_count < 3

Well I would not use any function. 好吧,我不会使用任何功能。 it looks pretty straight forward to me. 对我来说看起来很直白。 The quickest would be 最快的是

SELECT * FROM   #temp s
WHERE ( SELECT  COUNT(*)  FROM    #temp  f WHERE f.xDate = s.xDate AND  f.xCount >= s.xCount ) <= 2
Order by xDate, xCount desc

Check the full sample code here: 在此处检查完整的示例代码:

create table #temp (xDate datetime, xItem nvarchar(max), xCount int);

insert into #temp
select
'2018-01-01','A', 100 union all 
select '2018-01-01','B', 200 union all 
select '2018-01-01','D', 500 union all 
select '2018-01-02','C', 200 union all 
select '2018-01-02','E', 800


SELECT * FROM   #temp s
WHERE ( SELECT  COUNT(*)  FROM    #temp  f WHERE f.xDate = s.xDate AND  f.xCount >= s.xCount ) <= 2
Order by xDate, xCount desc

drop table #temp;

Another method is to use TOP, CROSS APPLY. 另一种方法是使用TOP,CROSS APPLY。

;WITH CTE AS
(
select 
distinct xDate
from Your_Table
)
SELECT 
T.xDate,
T1.xItem,
T1.xCount
FROM CTE T
CROSS APPLY (SELECT TOP 2 xItem,xCount FROM Your_Table WHERE xDate=T.xDate ORDER BY xCount DESC ) T1

Just another one suggestion using DENSE_RANK() : 另一个使用DENSE_RANK()建议:

DECLARE @FooTable TABLE
(
    xDate VARCHAR(25),
    xItem VARCHAR(10),
    xCount INT  
)

INSERT INTO @FooTable
(
    xDate,
    xItem,
    xCount
)
VALUES
  ('2018-01-01',   'A',           100)
, ('2018-01-01',   'B',           200)
, ('2018-01-01',   'D',           500)
, ('2018-01-02',   'C',           200)
, ('2018-01-02',   'E',           800)

SELECT 
s.*
FROM 
(
    SELECT 
      ft.xDate
    , ft.xItem
    , ft.xCount
    --, ROW_NUMBER() OVER(PARTITION BY ft.xDate ORDER BY ft.xCount DESC) rn
    , DENSE_RANK() OVER (PARTITION BY ft.xDate ORDER BY ft.xCount desc) dr
    FROM @FooTable ft
)s
WHERE s.dr < 3

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM