如何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;
我有 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;