我有2张表,看起来像:
CustomerInfo(CustomterID, CustomerName)
CustomerReviews(ReviewID, CustomerID, Review, Score)
我想搜索字符串的评论并返回CustomerInfo.CustomerID
和CustomerInfo.CustomerName
。但是,我只希望显示不同的CustomerID
和CustomerName
以及CustomerReviews.Reviews
和CustomerReviews.Score
中的一个。我还想通过CustomerReviews.Score
订购。
我无法弄清楚如何做到这一点,因为客户可以留下多个评论,但我只想要一个评分最高的客户列表。
有什么想法吗?
答案 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