Отображение отдельных элементов из сгруппированных строк в одной строке

#sql #sql-server

Вопрос:

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

Исходные Данные

 rDate      | track | horse | odds
-----------------------------
01/06/2021 | Ascot | Jim   | 3
01/06/2021 | Ascot | Dave  | 3
01/06/2021 | Ascot | Rex   | 15
01/06/2021 | Epsom | Lee   | 2
01/06/2021 | Epsom | Ben   | 3
01/06/2021 | Epsom | Gary  | 4
 

Сгруппированы по дате, треку, среднему значению(коэффициентам)

 Select rDate, track, AVG(odds)
FROM Results
GROUP BY rDate, track

rDate      | track | AvgOdds
-----------------------------
01/06/2021 | Ascot | 7
01/06/2021 | Epsom | 3
 

Желаемый результат, сгруппированный со средними коэффициентами, но также с индивидуальными коэффициентами, добавленными в сгруппированную строку:

 rDate      | track | AvgOdds | odds1 | odds2 | odds3
--------------------------------------------------
01/06/2021 | Ascot |    7    |   3   |   3   |   15
01/06/2021 | Epsom |    3    |   2   |   3   |   4
 

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

Комментарии:

1. Посмотрите на использование сводного запроса, вы должны быть в состоянии сделать все это за один раз.

2. Поворот-лучший вариант для запросов такого типа. Если вы не хотите использовать Pivot, тогда ищите только другие решения.

3. Вы можете сделать это с помощью a conditional case , если количество лошадей всегда одинаково (вам понадобится столбец для назначения критериев заказа), или вы ожидаете, что это будет работать с переменным количеством лошадей на дорожку?

4. @Stu да, это альтернативное решение. Но SQL Server предоставляет СВОДНЫЕ данные. Если не использовать PIVOT, то запрос будет немного длинным. В случае, если пользователь не готов к pivot, предоставьте только решение для оператора case.

5. Сначала вам нужно будет заставить его работать для вашего конкретного набора данных; для переменного числа строк в группе единственным приемлемым вариантом будет динамический SQL для построения переменного числа критериев сводки или обращения.

Ответ №1:

Я бы предложил условную агрегацию, сформулированную следующим образом:

 SELECT rDate, track, AVG(odds) as avgodds,
       MAX(CASE WHEN seqnum = 1 THEN odds END) as odds1,
       MAX(CASE WHEN seqnum = 2 THEN odds END) as odds2,
       MAX(CASE WHEN seqnum = 3 THEN odds END) as odds3
FROM (SELECT r.*,
             ROW_NUMBER() OVER (PARTITION BY rDate, Track ORDER BY odds) as seqnum
      FROM Results r
     ) r
GROUP BY rDate, track;
 

Примечание: Если вы хотите расширить это до 8 столбцов для коэффициентов, просто следуйте шаблону в SELECT .

Ответ №2:

вы можете использовать следующий запрос

 select rDate,track,max(AvgOdds) as AvgOdds,MAX(odds1) as odds1,MAX(odds2) as odds2,MAX(odds3) as odds3 
from
  (select rDate,track,AvgOdds,
       case when seq = 1 then odds else '' end as odds1,
       case when seq = 2 then odds else '' end as odds2,
       case when seq = 3 then odds else '' end as odds3
  from
    (Select rDate, track, 
           AVG(odds) over(partition by rDate, track) as AvgOdds,
           ROW_NUMBER()over(partition by rDate, track order by rdate) as seq,odds
     FROM Results) t) result
group by rDate,track
 

результат: dbfiddle.uk