How to choose top salaries for each person?

I have a 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

I want to choose the top 2 salaries for each person.

I'm trying to understand the cross. It seems that my invented task corresponds to the cross.

I now have the following query

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

look like I'm far enough from the expected result.

Expected Result:

1    180
1    200
2    40
2    45
+4
source share
7 answers

You can use OUTER APPLY with 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

Will return:

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

Another way:

;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

The same way out.

+3
source

You are close, just not choosing the right values:

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 .

+3

By With Statement

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
+1

.

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

SELECT * FROM           (                 user_id,                , dense_rank() OVER ( user_id ORDER BY desc)             ) a a.ranking <= 2 order by a.user_id

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
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;
0

Source: https://habr.com/ru/post/1655481/


All Articles