SF *_*per 7 sql t-sql sql-server
我正在2012 MS-SQL服务器上运行,并且在其他字段中有一个包含Age,Gender的表USER,以及一个包含销售记录的SALES表.
我目前正在计算销售排行榜,显示由其销售人员订购的销售人员列表,以便举例说明此列表根据其最高销售额返回各种销售代表.在列表中间的某个地方,我们有托马斯先生,让我们说#4.
我目前的任务是展示Thomas与具有与他相同年龄的销售代表的比较,以及他与具有与他相同性别的销售代表的比较.计算将返回与上述整体列表不同的结果.
我理想的存储过程将收到1个参数(UserId)并返回以下单个记录值:OverallPosition,OverallPositionTotalCount,AgePosition,AgeTotalCount,GenderPosition,GenderTotalCount
数据样本:
CREATE TABLE dbo.User
(
UserId int NOT NULL IDENTITY (1, 1),
Name nvarchar(50) NOT NULL,
Age int NULL,
Gender nvarchar(10) NULL
)
1, James, 30, 'male'
2, Monica, 27, 'female'
3, Paul, 30, 'male'
4, Thomas, 30, 'male'
5, Mike, 22, 'male'
6, Sabrina, 30, 'female'
CREATE TABLE dbo.Sales
(
SalesId int NOT NULL IDENTITY (1, 1),
UserId int NOT NULL,
TotalSale int NOT NULL
) ON [PRIMARY]
1, 1, $900,000
2, 1, $1,000,000
3, 2, $900,000
4, 2, $400,000
5, 3, $750,000
6, 3, $300,000
7, 4, $875,000
8, 5, $700,000
9, 5, $1,200,000
10, 6, $850,000
Run Code Online (Sandbox Code Playgroud)
销售排行榜列表
SELECT u.UserId, u.Name, MAX(s.TotalSale) as TopSale, Count(*) OVER () AS TotalCount
FROM User u
INNER JOIN Sales s on s.UserId = u.UserId
GROUP BY u.UserID, u.Name
ORDER BY TopSale DESC
OFFSET (@PageIndexSelected) * @PageCountSelected ROWS
FETCH NEXT @PageCountSelected ROWS ONLY
Run Code Online (Sandbox Code Playgroud)
理想的计算结果
由于托马斯(userId 4)是30岁和"男性",他的统计数据应该是这样的
OverallPosition = 4; OverallPositionTotalCount = 6 (i.e 4 out of 6)
$1,200,000 Mike
$1,000,000 James
$900,000 Monica
$875,000 Thomas
$850,000 Sabrina
$750,000 Paul
AgePosition = 2; AgeTotalCount = 4 (i.e. 2 out of 4)
$1,000,000 James
$875,000 Thomas
$850,000 Sabrina
$750,000 Paul
GenderPosition = 3; GenderTotalCount = 4 (i.e 3 out of 4)
$1,200,000 Mike
$1,000,000 James
$875,000 Thomas
$750,000 Paul
Run Code Online (Sandbox Code Playgroud)
注意
预期结果只是单个用户的OverallPosition,OverallPositionTotalCount,AgePosition,AgeTotalCount,GenderPosition,GenderTotalCount的值(存储过程将接收UserId作为参数)而不是实际列表.
EXPECTED RETURN
OverallPosition = 4,
OverallPositionTotalCount = 6,
AgePosition = 2,
AgeTotalCount = 4,
GenderPosition = 3,
GenderTotalCount = 4
正如我在评论中所说,我真的不知道如何解决这个问题.我希望有人愿意帮忙!
第一个CTE获得每个人的最大销售额.第二个使用窗口函数rank()并count()使用适当的over()子句来计算位置和总数.
with C1 as
(
select U.UserId,
U.Gender,
U.Age,
max(S.TotalSale) as TotalSale
from dbo.[User] as U
inner join dbo.Sales as S
on U.UserId = S.UserId
group by U.UserId,
U.Gender,
U.Age
), C2 as
(
select C1.UserId,
C1.TotalSale,
rank() over(order by C1.TotalSale desc) as OverallPosition,
rank() over(partition by C1.Age order by C1.TotalSale desc) as AgePosition,
rank() over(partition by C1.Gender order by C1.TotalSale desc) as GenderPosition,
count(*) over() as OverallPositionTotalCount,
count(*) over(partition by C1.Age) as AgeTotalCount,
count(*) over(partition by C1.Gender) as GenderTotalCount
from C1
)
select C2.OverallPosition,
C2.OverallPositionTotalCount,
C2.AgePosition,
C2.AgeTotalCount,
C2.GenderPosition,
C2.GenderTotalCount
from C2
where C2.UserId = 4;
Run Code Online (Sandbox Code Playgroud)
替代方案:
select C.OverallPosition,
C.OverallPositionTotalCount,
C.AgePosition,
C.AgeTotalCount,
C.GenderPosition,
C.GenderTotalCount
from (
select U.UserId,
S.TotalSale,
rank() over(order by S.TotalSale desc) as OverallPosition,
rank() over(partition by U.Age order by S.TotalSale desc) as AgePosition,
rank() over(partition by U.Gender order by S.TotalSale desc) as GenderPosition,
count(*) over() as OverallPositionTotalCount,
count(*) over(partition by U.Age) as AgeTotalCount,
count(*) over(partition by U.Gender) as GenderTotalCount
from dbo.[User] as U
cross apply (
select max(S.TotalSale) as TotalSale
from dbo.Sales as S
where U.UserId = S.UserId
) as S
) as C
where C.UserId = 4;
Run Code Online (Sandbox Code Playgroud)