Как ВЫБРАТЬ ОТЛИЧНУЮ ИНФОРМАЦИЮ с ТОП 1 Инфо и Заказом ИЗ ТОП 1 Инфо - PullRequest
5 голосов
/ 04 июня 2010

У меня есть 2 таблицы, которые выглядят так:

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

Я хочу найти отзывы для строки и вернуть CustomerInfo.CustomerID и CustomerInfo.CustomerName. Тем не менее, я хочу показать только отдельные CustomerID и CustomerName вместе с одним из их CustomerReviews.Reviews и CustomerReviews.Score. Я также хочу заказать по CustomerReviews.Score.

Я не могу понять, как это сделать, так как клиент может оставить несколько отзывов, но мне нужен только список клиентов с их наибольшим количеством набранных отзывов.

Есть идеи?

Ответы [ 3 ]

5 голосов
/ 04 июня 2010

Это самая большая проблема для каждой группы, которая возникала десятки раз при переполнении стека.

Вот решение, которое работает с оконной функцией:

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;

И вот решение, которое более широко работает с брендами РСУБД, которые не поддерживают оконные функции:

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 голос
/ 04 июня 2010

Я голосовал за ответ Билла Карвина, но думал, что выброшу другой вариант.

Используется коррелированный подзапрос , который часто может вызывать проблемы с производительностью больших наборов данных, поэтому используйте его с осторожностью Я думаю, что единственным преимуществом является то, что запрос легче понять сразу.

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 голосов
/ 04 июня 2010

Я думаю, что это должно сделать

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
...