2015-05-26 1 views
0

Я довольно новичок в SQL и пытаюсь вычислить новое поле на основе 3 очень больших таблиц базы данных. Вот абстракция:Новое поле с расчетом даты из нескольких таблиц: обновление или процедура?

  • Таблица 1: игроки (содержит поле даты рождения)
  • Таблица 2: турниры (содержит поле DATETIME)
  • Таблица 3: игры (имеет внешние ключи, ссылающийся players.id и tournament.id)

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

Должен ли я написать цикл процедур/операций для этого? или есть способ сделать это с помощью запроса на обновление?

+0

вы уверены, что хотите сохранить вычисленное значение? Если дата рождения корректируется или перенесенный турнир будет обрабатывать обновление калькулятора возрастное поле? –

+0

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

+0

Возможно, вы захотите взглянуть на расчет возраста в официальной документации, в которой используется функция TIMESTAMPDIFF: http://dev.mysql.com/doc/refman/5.0/en/date-calculations.html. Это просто получает целое число. Если вам нужны точные вычисления, посмотрите здесь алгоритм: http://stackoverflow.com/a/30377142/4665459 –

ответ

1

Вы можете сделать это с помощью UPDATE заявление. (Но, вы действительно хотите?)

Сначала напишите заявление SELECT, которое даст вам результат.

SELECT g.player_id 
    , g.tournament_id 
    , p.birthday 
    , t.tournament_date 
    , DATEDIFF(t.tournament_date,p.birthday) AS days_diff 
    FROM games g 
    JOIN player p ON p.id = g.player_id 
    JOIN tournament t ON t.id = g.tournament_id 

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

Затем вы можете использовать инструкцию SELECT как встроенное представление в инструкции UPDATE. Предполагая, что вы добавили age_in_days столбец в таблицу games

UPDATE games d 
    JOIN ( 
     SELECT g.player_id 
       , g.tournament_id 
       , p.birthday 
       , t.tournament_date 
       , DATEDIFF(t.tournament_date,p.birthday) AS days_diff 
      FROM games g 
      JOIN player p ON p.id = g.player_id 
      JOIN tournament t ON t.id = g.tournament_id 
     ) s 
    ON s.player_id  = d.player_id 
    AND s.tournament_id = d.tournament_id 
    SET s.age_in_days = s.days_diff 

Далее, мы должны быть обеспокоены «большой» таблицей, и избежать огромной сделки, которая генерирует лодку отката (если это Таблицы InnoDB).

Если это беспокойство, делать операцию UPDATE в «партиях», разбив его, добавив предикат в виде запроса инлайны, например, WHERE g.player_id = 42 и работает тот же UPDATE, один раз для каждого player_id.


Если вы хотите возраст в «десятичных годах», вам нужно разработать выражение, чтобы вернуть его. (В рудиментарном приближении разделить разницу в днях на количество дней в 365.25 году. Это было бы, чтобы вы очень близко.)


(В начале моего ответа, я спросил, действительно ли вы хочет.

Учтите, что если birthday значения игрока обновляется или tournament_date изменяется, расчетные значения, сохраненные в games таблицы будут непоследовательными.

+0

awesome! Спасибо. Я не знал, что вы можете присоединиться к запросу вместо таблицы. (Как я уже сказал, я новый XD) – user3925713

+0

Остерегайтесь встроенных просмотров и последствий для производительности. (Запрос SELECT, завернутый в parens, который обрабатывается как таблица. MySQL вызывает это «производную таблицу». Результаты запроса материализуются во временную таблицу, а затем внешний оператор работает против «временного» «table. Я помещаю временные кавычки, потому что это отличается от фактической« ВРЕМЕННОЙ ТАБЛИЦЫ ».) Существуют и другие шаблоны запросов, которые могут быть использованы, но я просто привел пример одного подхода. – spencer7593

0

Вы можете попробовать это

Update games 
set age = (SELECT FLOOR(DATEDIFF(DAY, players.BirthDate, tournaments.datetime)/365.25) from players,tournaments) 
where players.id=games.id; 
Смежные вопросы