我有一个业务场景,其中边缘案例很少。让我用 Stack Overflow Privileges 数据解释一下。
请找到权限模式创建和示例数据:https://rextester.com/KQZS91498
根据给定的声誉输入,我需要找到最近的特权。即,最近的特权小于接下来可以实现的给定声誉和特权。
示例:如果我提供 7276 的声誉,我需要以下权限作为输出:
Id Reputation PrivilegeName
------------------------------------------
22 5000 approve tag wiki edits
23 10000 access to moderator tools
我正在使用以下查询来实现它。
DECLARE @MyReputation AS INT = 7276;
DECLARE @FromId AS INT = 0;
DECLARE @ToId AS INT = 0;
SELECT @FromId = MAX(Id) FROM @Privilege
WHERE Reputation > 0 AND Reputation <= @MyReputation;
SELECT @ToId = MIN(Id) FROM @Privilege
WHERE @MyReputation > 0 AND @MyReputation < Reputation;
SELECT Id, Reputation, PrivilegeName
FROM @Privilege
WHERE Id IN (@FromId, @ToId)
ORDER BY Id;
它给了我预期的结果。
请找到相同的可执行查询: https://rextester.com/PDEXOM92503 。
由于我使用聚合函数来获取 Id,因此如果声誉具有多个特权,则它不起作用。
这里的声望 10 包含两个特权。而且有可能在 future ,它可能拥有三个或更多的特权。
所以期望是,如果我将我的声誉输入提供为 10 或 13 ,我需要输出为:
Id Reputation PrivilegeName
----------------------------------------------
3 10 remove new user restrictions
4 10 create wiki posts
5 15 flag posts
6 15 vote up
对于 945 的声誉输入:
Id Reputation PrivilegeName
------------------------------------------
15 500 access review queues
16 1000 established user
17 1000 create gallery chat rooms
即,基于给定声誉输入的最接近的可能特权。
该案例适用于 100 、 1000 等对同一声誉拥有多个特权的声誉。
实现我上面提到的期望的最佳方法是什么?
最佳答案
你也可以像下面一样使用 UNION ALL
。
;WITH cte
AS (SELECT *,
reputation - @MyReputation DIFF
FROM @Privilege)
SELECT *
FROM cte
WHERE diff = (SELECT Max(diff)
FROM cte
WHERE diff <= 0)
UNION ALL
SELECT *
FROM cte
WHERE diff = (SELECT Min(diff)
FROM cte
WHERE diff > 0)
Online Demo
以上查询也可以使用
CASE WHEN
编写,如下所示;WITH cte
AS (SELECT *,
reputation - @MyReputation diff,
Max(CASE
WHEN reputation - @MyReputation <= 0 THEN
reputation - @MyReputation
END)
OVER() mind,
Min(CASE
WHEN reputation - @MyReputation > 0 THEN
reputation - @MyReputation
END)
OVER() maxd
FROM @Privilege)
SELECT Id,Reputation,PrivilegeName,DetailedDescription
FROM cte
WHERE diff in (mind,maxd)
关于sql - 根据给定的声誉获得最近的特权,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55240889/