T-SQL сгруппировать по задачам - PullRequest
6 голосов
/ 24 января 2011

У меня есть следующая проблема (или, может быть, просто барьер мышления):

У меня есть таблица (фактически представление из таблицы) со следующими столбцами и данными:

http://i.stack.imgur.com/n98Sw.png

Теперь я хочу сгруппировать эти данные по столбцу «Клиент» и получить «CompetitorName» с наибольшим «CompetitorCount». Конечно, я могу создать такой запрос:

SELECT Customer, MAX(CompetitorCount) FROM MyTable GROUP BY Customer

Это вернет две строки:

Foo; 12  
Bar; 7

Но я не смогу получить CompetitorName таким образом. Если я включу его в группу по разделам, «Клиент» появится несколько раз. В противном случае мне нужно использовать агрегатную функцию, чтобы выбрать, какое «CompetitorName» я хочу использовать, но, конечно, MAX не работает.

Я уверен, что это можно как-то сделать, но сейчас я понятия не имею, как.

Заранее спасибо за любую помощь.

Ответы [ 2 ]

7 голосов
/ 24 января 2011
select customer, competitorname, competitorcount
FROM
(
 select *, rn = ROW_NUMBER() over (
  partition by customer order by competitorcount desc)
 from tbl
) X
WHERE rn=1

Если вы хотите показать TIES при значении Max, измените ROW_NUMBER () на RANK ().

Возможно, вы даже найдете версию cross apply быстрее, но она не работает длясвязей.TOP 1 обеспечивает единую запись при наличии связей между конкурентами.

select C.*
FROM
(select distinct customer from tbl) A
cross apply
(select top 1 B.*
 from tbl B
 where A.customer = B.customer
 order by B.competitorcount desc) C

Сначала выбираются все отдельные клиенты.Затем для каждого клиента он отключается и извлекает записи с МАКС (счет участника) для этого клиента.

3 голосов
/ 24 января 2011

Есть несколько способов сделать это, но самый простой способ:

WITH Custs AS (
   SELECT 
      Customer, 
      CompetitorName,
      CompetitorCount,
      ROW_NUMBER() OVER (PARTITION BY Customer ORDER BY CompetitorCount DESC) AS __ROW
   From MyTable
)
SELECT
    Customer,
    CompetitorName,
    CompetitorCount
FROM Custs
WHERE __ROW = 1;

и, если вы хотите, чтобы связи (где наибольшее количество связывалось для клиента, и вы хотите указать обе строки), используйте RANK () вместо ROW_NUMBER () в Выше запрос.

Вы также можете сделать это с помощью самостоятельного соединения:

WITH Custs AS (
    SELECT Customer, MAX(CompetitorCount) AS CompetitorCount
    FROM MyTable 
    GROUP BY Customer)
SELECT m.Customer, m.CompetitorName, m.CompetitorCount
FROM MyTable m
INNER JOIN Custs c
   ON  c.CompetitorCount = m.CompetitorCount
   AND c.Customer        = m.Customer;
...