如何为每个人选择前N名工资?

时间:2016-09-22 12:56:46

标签: sql sql-server join cross-apply

我有桌子

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

我想为每个人选择前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

7 个答案:

答案 0 :(得分:3)

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

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方法实际上可能更快。

答案 1 :(得分:3)

你可以使用OUTER APPLY和TOP 2:

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

将返回:

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

相同的输出。

答案 2 :(得分:1)

使用Partition By和With Statement

@fields(key = "sample")
static public  int data = 2;

答案 3 :(得分:0)

试试这个。

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
                              )
              )

答案 4 :(得分:0)

试试这个

SELECT * FROM             (选择                   user_id,薪水                  ,dense_rank()OVER(由user_id ORDER BY salary desc分区)作为排名              来自薪水)a 通过a.user_id

命令a.ranking&lt; = 2

答案 5 :(得分:0)

您可以使用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

答案 6 :(得分:0)

您也可以使用以下查询。

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;