对表中的每一行进行排名,并将行分组为重复项,而不重置每个组的排名

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对表中的每一行进行排名,并将行分组为重复项,而不重置每个组的排名相关的知识,希望对你有一定的参考价值。

我跟我一起创建了下表:

dishname         rating rank
Fish Fry          5.0    1
Tandoori Chicken  4.8    2
Tandoori Chicken  4.6    3
Paneer Tikka      4.5    4
Baby Corn         4.2    5
Fish Fry          4.1    6
Paneer Tikka      3.9    7
Baby Corn         3.1    8
Fish Fry          2.9    9
Paneer Tikka      2.3   10

*假设每道菜都来自不同的餐厅

使用的代码:

Select dishname,
       rating, 
       Row_Number() Over(Order By rating desc) as Rank 
From DISH

这就是我想要实现的目标:

dishname          rating  rank
Fish Fry           5.0     1
Fish Fry           4.1     6
Fish Fry           2.9     9
Tandoori Chicken   4.8     2
Tandoori Chicken   4.6     3
Paneer Tikka       4.5     4
Paneer Tikka       3.9     7
Paneer Tikka       2.3     10
Baby Corn          4.2     5
Baby Corn          3.1     8

我希望将等级为1的菜放在桌子的顶部,然后是相同的菜(如上所示,具有不同的等级)。一旦完成,那么选择下一道菜的标准应该是检查下一个等级(对于不同的菜)。每组的第一道菜是根据Rank栏选择的,并且在组内,菜肴应按等级排序。

有四种菜肴的当前餐桌 Please click for picture

我期待什么 Please click for picture

答案

你可以用它。

DECLARE @DISH TABLE ( dishname varchar(20), rating decimal(18,2) )
INSERT INTO @DISH VALUES 
('Fish Fry'          ,5.0),
('Tandoori Chicken'  ,4.8),
('Tandoori Chicken'  ,4.6),
('Paneer Tikka'      ,4.5),
('Baby Corn'         ,4.2),
('Fish Fry'          ,4.1),
('Paneer Tikka'      ,3.9),
('Baby Corn'         ,3.1),
('Fish Fry'          ,2.9),
('Fish Fry'          ,1.9),
('Paneer Tikka'      ,2.3),
('Tandoori Chicken'  ,3.2),
('Tandoori Chicken'  ,1.7),
('Paneer Tikka'      ,2.0)



SELECT dishname, rating, Rank  
FROM (
    SELECT *,
        Row_Number() Over(Order By SubRank, rating desc) as Rank,
        MAX(rating) OVER(PARTITION BY SubRank, dishname) as FirstOrdeR
    FROM (
        Select dishname,
               rating, 
               ((Row_Number() Over(PARTITION BY dishname ORDER BY rating desc))-1) / 3 as SubRank 
        From @DISH
    ) AS T 
) AS X
ORDER BY SubRank, FirstOrder DESC, Rank 

结果:

dishname             rating                                  Rank
-------------------- --------------------------------------- --------------------
Fish Fry             5.00                                    1
Fish Fry             4.10                                    6
Fish Fry             2.90                                    10
Tandoori Chicken     4.80                                    2
Tandoori Chicken     4.60                                    3
Tandoori Chicken     3.20                                    8
Paneer Tikka         4.50                                    4
Paneer Tikka         3.90                                    7
Paneer Tikka         2.30                                    11
Baby Corn            4.20                                    5
Baby Corn            3.10                                    9
Paneer Tikka         2.00                                    12
Fish Fry             1.90                                    13
Tandoori Chicken     1.70                                    14
另一答案

你可以这样做:

我使用CROSS APPLY选择最小排名,并将其用作排序顺序。

       declare @myt table (dishname  nvarchar(50),       rating float, rank int)
insert into @myt
values 

('Fish Fry'          ,5.0  , 1),
('Tandoori Chicken'  ,4.8  , 2),
('Tandoori Chicken'  ,4.6  , 3),
('Paneer Tikka'      ,4.5  , 4),
('Baby Corn'         ,4.2  , 5),
('Fish Fry'          ,4.1  , 6),
('Paneer Tikka'      ,3.9  , 7),
('Baby Corn'         ,3.1  , 8),
('Fish Fry'          ,2.9  , 9),
('Paneer Tikka'      ,2.3  ,10)



select z.Dishname,rating,[rank] from (
select *,ROW_NUMBER() over(partition by dishname order by [Rank] asc,rating desc) rn from (

Select dishname,
       rating, 
       Row_Number() Over(Order By rating desc) as [Rank] 
From @myt
)X 
) z

cross apply (select  MIN(rank) as sortorder,dishname from @myt s

where s.dishname = z.dishname group by dishname) f

order by sortorder,rn

结果

enter image description here

另一答案

这里的过程是能够在每个菜的排名和最佳排名之间加入。然后可以先排序最好的排名。

with ranking as (
    select dishname, rating, rank() over(order by rating) as dr
    from Dish
), topRanking as (
    select dishname, max(dr) as maxRank
    from ranking
    group by dishname
)
select r.dishname, r.rating
from ranking r
    inner join topRanking tr on tr.dishname = r.dishname
order by maxRank desc, rating desc
另一答案

基于单CTE的方法,虽然可能比其他答案效率低一点:

--DECLARE @TABLE TABLE(dishname varchar(10), rating decimal(2,1))
--INSERT INTO @TABLE VALUES ('Fish', 5.0), ('Chicken', 4.8), ('Chicken', 4.6), ('Tikka', 4.5), ('Corn', 4.2), ('Fish', 4.1), ('Tikka', 3.9), ('Corn', 3.1), ('Fish', 2.9), ('Tikka', 2.3) /* extra records */ , ('Fish', 1.9), ('Chicken', 3.2), ('Chicken', 1.7), ('Tikka', 2.0)

;WITH CTE AS (
    SELECT
        *
      , [Rank] = ROW_NUMBER() OVER(ORDER BY rating DESC)
      , [Group] = (ROW_NUMBER() OVER(PARTITION BY dishname ORDER BY rating DESC) - 1) / 3
    FROM @TABLE
)
SELECT *
FROM CTE AS A
ORDER BY [Group], (SELECT MIN([Rank]) FROM CTE AS B WHERE A.dishname = B.dishname AND A.[Group] = B.[Group]), rating DESC
另一答案
Select dishname,rating, Row_Number() Over as Rank From DISH where order by dishname('Fish Fry','Tandoori Chicken','Panner Tikka','Baby Corn') order by Over DESC;

这是mysql特有的

以上是关于对表中的每一行进行排名,并将行分组为重复项,而不重置每个组的排名的主要内容,如果未能解决你的问题,请参考以下文章

如何将表中的每一行与所有行进行比较?

从表中的多个重复项中删除特定记录

在 Node.js 中为 postgres 表中的每一行以不同的间隔为每一行运行重复任务

对分组内的行进行排名(2 列)

MySQL连接和连接行而不重复条目[重复]

如何使用Scala的DataFrame比较表中的每一列而不关心列是啥? [重复]