SQL 服务器在不显示完整结果集的情况下获得排名?

SQL Server get the rank without showing the full result set?

假设我有一个 Customer table 和一个 Purchase table,Customer 和 [=12 之间存在一对零或多对多的关系=].

我知道我可以使用 SQL 服务器中的 rank() 功能来获取,例如,根据购买金额排名前 10 位的客户。但我也想获得特定客户在整个系统中的排名,但不返回排名在该客户之前的客户的整个数据集。

我对 SQL 有点生疏(Entity Framework 的错,哈哈)所以我无法为这个查询构建有效的语句。有人知道 rank() 或其他功能是否可以做到这一点吗?

您可以使用聚合查询执行此操作:

select count(customerid) + 1
from t
where t.value < (select t2.value from t t2 where t2.customerid = @customerid);

请注意,这专门做了一个 rank()dense_rank()row_number().

需要类似(但不同)的逻辑

此查询可以充分利用 (customerid, value)(value, customerid) 上的索引。

这听起来很适合 CTE 并使用您提到的 window 函数。您可以声明特定客户,使用 CTE 获取所有客户的购买金额,使用第二个 cte 对所有客户进行排名,然后查询前 10 名并合并特定客户信息。如果第 11 个人已经在前 10 名中,则 union 将删除它们。 UNION ALL 将为您提供重复记录,但提供 11 行。

DECLARE @userID INT = xxxx

;WITH cte1 AS (
SELECT 
customerID
, SUM(purchase_dollars) AS purchase_amount
FROM customer_table

GROUP BY customerID)

, cte_rank AS (
SELECT 
customerID
, RANK() OVER(ORDER BY purchase_amount DESC) AS purchase_amount_rank
--, ROW_NUMBER() OVER(ORDER BY purchase_amount DESC) AS purchase_amount_rank --This will get you 10 records
FROM cte1)

SELECT 
t1.CustomerID
, t2.purchase_amount_rank

FROM customer_table t1
INNER JOIN cte_rank t2
ON t1.customerid = t2.customerid
WHERE t2.purchase_amount_rank <= 10

UNION 

SELECT t1.customerID
, t2.purchase_amount_rank
FROM customer_table t1
INNER JOIN cte_rank t2
ON t1.customerid = t2.customerid
AND t1.customer_id = @userID

ORDER BY t2.purchase_amount_rank