如何使用 TOP 1 信息和来自 Top 1 信息的排序依据选择不同的信息

发布于 2024-09-04 03:32:34 字数 507 浏览 5 评论 0原文

我有 2 个表,看起来像:

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

我想搜索评论中的字符串并返回 CustomerInfo.CustomerIDCustomerInfo.CustomerName。但是,我只想显示不同的 CustomerIDCustomerName 以及它们的 CustomerReviews.ReviewsCustomerReviews.Score 之一代码>.我还想通过 CustomerReviews.Score 进行订购。

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

有什么想法吗?

I have 2 tables, that look like:

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

I want to search reviews for a string and return CustomerInfo.CustomerID and CustomerInfo.CustomerName. However, I only want to show distinct CustomerID and CustomerName along with just one of their CustomerReviews.Reviews and CustomerReviews.Score. I also want to order by the CustomerReviews.Score.

I can't figure out how to do this, since a customer can leave multiple reviews, but I only want a list of customers with their highest scored review.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

跨年 2024-09-11 03:32:34

这是每组中最大的问题,在 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 带有通配符。

This is the greatest-n-per-group problem that has come up dozens of times on Stack Overflow.

Here's a solution that works with a window function:

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;

And here's a solution that works more broadly with RDBMS brands that don't support window functions:

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;

I'm showing the CONTAINS() function because you should be using the fulltext search facility in SQL Server, not using LIKE with wildcards.

玻璃人 2024-09-11 03:32:34

我投票支持比尔·卡文的答案,但我想我应该放弃另一个选择。

它使用 相关子查询,对于大数据集经常会出现性能问题,所以要谨慎使用。我认为唯一的好处是查询更容易立即理解。

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

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

I voted for Bill Karwin's answer, but I thought I'd throw out another option.

It uses a correlated subquery, which can often incur performance problems with large data sets, so use with caution. I think the only upside is that the query is easier to immediately understand.

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

I didn't add the string search filter, but that can be easily added.

过度放纵 2024-09-11 03:32:34

我认为这应该可以做到

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

I think this should do it

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文