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
假设我有一个 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