我有一个业务场景,其中边缘案例很少。让我用 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/

10-13 00:52