首页 > 解决方案 > T-SQL,如何获得前三个最大值,如果重复,包括它们?

问题描述

如标题所述,我希望选择前 3 个值,如果计数的值重复,也包括它。

SELECT b.planID, count(b.planID) AS PopularPlan
FROM dbo.Subscriber as b
GROUP BY B.planID
ORDER BY count(b.planID) DESC;

此输出返回所有最大值,例如:

PlanID  PopularPlan
 101    2555
 123    2555
 432    2390
  23    2390
  45    2090
  12    2080
  55    2090

如果我要使用 TOP 3,请选择 TOP 3,使用以下 SQL:

SELECT TOP 3 b.planID, count(b.planID) AS PopularPlan
FROM dbo.Subscriber as b
GROUP BY B.planID
ORDER BY count(b.planID) DESC;

它将返回以下内容:

PlanID  PopularPlan
 101    2555
 123    2555
 432    2390

在这种情况下,所需的输出将是做我想要的:

PlanID  PopularPlan
     101    2555
     123    2555
     432    2390
      23    2390
      45    2090

我知道 TOP 3 仅限于三个结果,但我似乎无法弄清楚如何添加重复的方法。

此外,如果我要包括 WITH TIES:

SELECT TOP 3 WITH TIES b.planID, count(b.planID) AS PopularPlan
FROM dbo.Subscriber as b
GROUP BY B.planID
ORDER BY count(b.planID) DESC;

这种情况下的输出是:

PlanID  PopularPlan
     101    2555
     123    2555
     432    2390
      23    2390

经测试,如果我选择 TOP 5,则会出现 2090 值,但我希望尽可能对 TOP 3 执行相同操作,以便输出保持原样:

PlanID  PopularPlan
     101    2555
     123    2555
     432    2390
      23    2390
      45    2090 <- has to have this value too

标签: sqltsql

解决方案


DENSE_RANK() 是你的朋友:

WITH cteOriginal AS
(
    SELECT b.planID, count(b.planID) AS PopularPlan
    FROM dbo.Subscriber as b
    GROUP BY B.planID
)
, cteDenseRank AS
(
    SELECT *, DENSE_RANK() OVER( ORDER BY PopularPlan DESC) AS DRank
    FROM cteOriginal
)
SELECT planID, PopularPlan
FROM cteDenseRank
WHERE DRank <= 3
ORDER BY PopularPlan DESC
;

大概你可以将两个 CTE 合并在一起,但我不确定 OVER 函数是如何与 GROUP BY 交互的,所以我做了这个稍微长一点的方法。

我个人可以说,自从 ROW_NUMBER()、RANK() 和 DENSE_RANK() 窗口函数出现在 T-SQL(2008 年?)之后,我几乎不再使用 TOP。

已编辑 - DENSE_RANK() 显示最佳结果。


推荐阅读