Объединить одну строку из таблицы в MySQL - PullRequest
4 голосов
/ 25 июня 2010

У меня есть две таблицы players и scores.

Я хочу создать отчет, который выглядит примерно так:

player    first score             points
foo       2010-05-20              19
bar       2010-04-15              29
baz       2010-02-04              13

Прямо сейчас мой запрос выглядит примерно такthis:

select p.name        player,
       min(s.date)   first_score,
       s.points      points    
from  players p    
join  scores  s on  s.player_id = p.id    
group by p.name, s.points

Мне нужен s.points, связанный со строкой, которую возвращает min(s.date).Это происходит с этим запросом?То есть как я могу быть уверен, что получаю правильное значение s.points для объединенной строки?

Примечание: я думаю, это как-то связано с отсутствием плотного ранжирования в MySQL.Какой лучший обходной путь здесь?

Ответы [ 2 ]

6 голосов
/ 25 июня 2010

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

Вот мой обычный ответ:

select
  p.name        player,
  s.date        first_score,
  s.points      points

from  players p

join  scores  s
  on  s.player_id = p.id

left outer join scores  s2
  on  s2.player_id = p.id
      and s2.date < s.date

where
  s2.player_id is null

;

Другими словами, учитывая количество баллов s, попробуйте найти количество баллов s2 для того же игрока, но с более ранней датой. Если ранняя оценка не найдена, то s - самая ранняя.


Ваш комментарий о связях: у вас должна быть политика, которую следует использовать в случае ничьей. Одна возможность - если вы используете автоинкрементные первичные ключи, то с наименьшим значением будет более ранний. См. Дополнительный термин во внешнем соединении ниже:

select
  p.name        player,
  s.date        first_score,
  s.points      points

from  players p

join  scores  s
  on  s.player_id = p.id

left outer join scores  s2
  on  s2.player_id = p.id
      and (s2.date < s.date or s2.date = s.date and s2.id < s.id)

where
  s2.player_id is null

;

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

Что касается комментариев, которыми я поделился с @OMG Ponies, помните, что этот тип запросов чрезвычайно выигрывает от правильного индекса.

0 голосов
/ 25 июня 2010

Большинство RDMB даже не позволяют включать неагрегированные столбцы в предложение SELECT при использовании GROUP BY. В MySQL вы получите значения из случайных строк для неагрегированных столбцов. Это полезно, если у вас есть одно и то же значение в определенном столбце для всех строк. Поэтому хорошо, что MySQL не ограничивает нас, хотя это важная вещь для понимания.

Целая глава посвящена этому в SQL Antipatterns .

...