我有一个业务场景,其中几乎没有边缘情况。让我用 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包含两个特权。而且将来有可能,它可能会拥有三个或更多的权限。
所以期望是,如果我提供的声誉输入为 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)
上面的查询也可以使用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/