如何选择带有TOP 1信息的DISTINCT信息和来自前1个信息的订单

时间:2010-06-03 21:53:32

标签: sql-server select distinct greatest-n-per-group

我有2张表,看起来像:

CustomerInfo(CustomterID, CustomerName)
CustomerReviews(ReviewID, CustomerID, Review, Score)

我想搜索字符串的评论并返回CustomerInfo.CustomerIDCustomerInfo.CustomerName。但是,我只希望显示不同的CustomerIDCustomerName以及CustomerReviews.ReviewsCustomerReviews.Score中的一个。我还想通过CustomerReviews.Score订购。

我无法弄清楚如何做到这一点,因为客户可以留下多个评论,但我只想要一个评分最高的客户列表。

有什么想法吗?

3 个答案:

答案 0 :(得分:5)

这是Stack Overflow上出现了数十次最大的每组问题。

这是一个适用于窗口函数的解决方案:

WITH CustomerCTE (
  SELECT i.*, r.*, ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY Score DESC) AS RN
  FROM CustomerInfo i
  INNER JOIN CustomerReviews r ON i.CustomerID = r.CustomerID 
  WHERE CONTAINS(r.Review, '"search"')
)
SELECT * FROM CustomerCTE WHERE RN = 1
ORDER BY Score;

这是一个更广泛适用于不支持窗口功能的RDBMS品牌的解决方案:

SELECT i.*, r1.*
FROM CustomerInfo i
INNER JOIN CustomerReviews r1 ON i.CustomerID = r1.CustomerID 
  AND CONTAINS(r1.Review, '"search"')
LEFT OUTER JOIN CustomerReviews r2 ON i.CustomerID = r2.CustomerID 
  AND CONTAINS(r1.Review, '"search"')
  AND (r1.Score < r2.Score OR r1.Score = r2.Score AND r1.ReviewID < r2.ReviewID)
WHERE r2.CustomerID IS NULL
ORDER BY Score;

我正在显示CONTAINS()函数,因为您应该在SQL Server中使用全文搜索工具,而不是使用带有通配符的LIKE

答案 1 :(得分:1)

我投票支持Bill Karwin的回答,但我想我会抛出另一个选择。

它使用correlated subquery,这通常会导致大型数据集出现性能问题,因此请谨慎使用。我认为唯一的好处是查询更容易立即理解。

select *
from [CustomerReviews] r
where [ReviewID] =
(
    select top 1 [ReviewID]
    from [CustomerReviews] rInner
    where rInner.CustomerID = r.CustomerID
    order by Score desc
)
order by Score desc

我没有添加字符串搜索过滤器,但可以轻松添加。

答案 2 :(得分:0)

我认为应该这样做

select ci.CustomterID, ci.CustomerName, cr.Review, cr.Score
from CustomerInfo ci inner join 
(select top 1*
from CustomerReviews
where Review like '%search%'
order by Score desc) cr on ci.CustomterID = cr.CustomterID 
order by cr.Score
相关问题