2010-06-03 50 views
5

我有2个表,看起来像:如何SELECT DISTINCT信息与TOP 1的信息和订单从顶部1信息

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

我想寻找的评论为一个字符串,返回CustomerInfo.CustomerIDCustomerInfo.CustomerName 。但是,我只想显示不同的CustomerIDCustomerName以及CustomerReviews.ReviewsCustomerReviews.Score中的一个。我也想通过CustomerReviews.Score订购。

我不知道如何做到这一点,因为客户可以留下多个评论,但我只想要一个评分最高的评论的客户名单。

任何想法?

+0

所以,你想搜索一个字符串的评论,但带回 客户的得分最高的评论,即使它本身不符合字符串? – 2010-06-03 21:57:20

+0

客户是否有可能有多个评分相同的最高分值?如果是这样,你想要他们全部,或者只是其中的一个?如果只是其中之一,哪一个? (“我不在乎”不是一个有效的选项。) – 2010-06-03 22:26:07

+0

只是其中之一,但我希望该评论匹配字符串。 – 2010-06-03 22:29:40

回答

5

这是一个已经拿出了几十遍上堆栈溢出的最大正每组问题。

这里是与一个窗口功能有效的解决方案:

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

+0

谢谢。我确实启用了全文搜索。 – 2010-06-03 22:37:39

+0

非常感谢!这使得更有意义,并且看起来好像表现明智。我确实启用了全文,我所指的“分数”实际上是全文搜索的“排名”。我不确定是否有很多人对全文很熟悉。我想我可以用“等级”替换“得分”并加入CONTAINSTABLE。 – 2010-06-03 22:52:13

+0

太棒了!乐意效劳。 – 2010-06-03 23:19:03

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 
+0

有更快的查询吗?由于我将对每个客户记录执行单独的搜索,因此这似乎很慢,记录很多。 谢谢! – 2010-06-03 22:12:59

+0

我不知道任何其他方式,检查查询的执行计划? – alejandrobog 2010-06-03 22:20:16

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 

我没有添加字符串搜索过滤器,但可以很容易地添加。

+0

是的,但我试图避免相关的子查询,如果有另一个解决方案不相关。另一种解决方案通常*效率更高(虽然每个规则都有例外)。 – 2010-06-03 23:50:49