sql - 根据给定的声誉获取最近的特权

标签 sql sql-server sql-server-2012

我有一个业务场景,其中几乎没有边缘情况。让我用 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包含两个特权。而且将来有可能,它可能会拥有三个或更多的权限。

所以期望是,如果我提供的声誉输入为 1013,我需要的输出为:

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

即,基于给定信誉输入的最接近的可能权限。

该案例适用于像1001000这样的声誉,这些声誉对于同一声誉具有多个特权。

实现上述期望的最佳方式是什么?

最佳答案

您也可以使用 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/

相关文章:

mysql - SQL Group By Order BY 在日期时间列上降序

sql - 由于外键约束问题而插入 A 错误

sql-server - 从表变量更新表

php - 从表单向数据库表插入多行

SQL 服务器 : Get record with date closest to given date

sql - 如果剧集直接连续或重叠,则合并日期行

c# - Entity Framework 死锁

sql-server - ODBC SQL Server 驱动程序登录超时已过期

sql - 当存在打开事务时,如何避免 SQL 查询超时错误?

sql - LEFT JOIN 根据 WHERE 条件的位置给出不同的数据集