如何select每个人的工资top N?

How to select top N salaries for each person?

我有 table

user_id  salary month
1        100    1
1        150    2
1        200    3
1        180    4
1        140    5
2        10     1
2        40     2
2        20     3
2        15     4
2        45     5

我想select每个人的工资前2名。

我试着理解交叉应用。看起来我发明的任务符合交叉应用。

现在我有以下查询

select distinct(s.user_id) from Salary s
cross apply (
     select top 2 * from Salary  sal
     order by sal.salary desc
)sal

看起来我离预期的结果还差得远。

预期结果:

1    180
1    200
2    40
2    45

你很接近,只是没有选择正确的值:

select sal.*
from (select distinct s.user_id from Salary s) s cross apply
     (select top 2 sal.*
      from Salary sal
      order by sal.salary desc
     ) sal;

请注意,执行此操作的典型方法是使用 row_numbers()。我认为 apply 方法在某些情况下实际上可能更快。

使用 Partition By 和 With 语句

Declare @SeriesNo INT=2

;With X AS
(
    SELECT
        UserId,
        Salary,         
        Month_Name,
        ROW_NUMBER () OVER(PARTITION BY UserId Order BY Salary Desc) AS PartNo
    FROM @tblTest    
)
SELECT
    UserId,
    Salary,         
    Month_Name
FROM X
WHERE X.PartNo <=@SeriesNo

您可以对 TOP 2 使用 OUTER APPLY:

SELECT DISTINCT 
            y.[user_id],
            d.salary,
            d.[month]
FROM YourTable y
OUTER APPLY(
    SELECT TOP 2  *
    FROM YourTable
    WHERE y.[user_id] = [user_id]
    ORDER BY [user_id], salary DESC
    ) as d
ORDER BY [user_id], salary DESC

会 return:

user_id salary  month
1       200     3
1       180     4
2       45      5
2       40      2

另一种方式:

;WITH cte AS (
SELECT  *,
        ROW_NUMBER() OVER (PARTITION BY [user_id] ORDER BY salary DESC) as rn
FROM YourTable
)

SELECT [user_id], salary, [month]
FROM cte 
WHERE rn <= 2

相同的输出。

试试这个。

SELECT s.user_id, s.salary
FROM SALARY s
WHERE s.salary =
              (
               SELEACT MAX(ss.salary)
               FROM SALARY ss
               WHERE s.user_id = ss.user_id
              )
OR s.salary =
              (
               SELEACT MAX(ss.salary)
               FROM SALARY ss
               WHERE s.user_id = ss.user_id
               AND ss.salary < 
                              (
                               SELEACT MAX(sss.salary)
                               FROM SALARY sss
                               WHERE s.user_id = sss.user_id
                              )
              )

试试这个

SELECT * 来自 (SELECT user_id, 工资 ,dense_rank() OVER ( partition by user_id ORDER BY salary desc) 作为排名 来自工资)a WHERE a.ranking <=2 按 a.user_id

排序

您可以使用 row_number()

进行查询
;WITH cte
AS (SELECT
    *, ROW_NUMBER() OVER (PARTITION BY userid ORDER BY salary DESC) rn
FROM salaries)
SELECT
    userid,
    salary
FROM cte
WHERE rn <= 2

您也可以使用以下查询。

DECLARE @TopFilter AS TINYINT = 2;
SELECT  TOP (1) WITH TIES user_id, salary
FROM    Salary
ORDER BY (ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY salary DESC) - 1 ) / @TopFilter + 1;