2009-05-18 1 views
0

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

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

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

GAME 
`game`.id 
`game`.home_team_id 
`game`.away_team_id 
`game`.number_of_periods 

GOAL 
// Records for each goal scored in the game 
`goal`.id 
`goal`.game_id 
`goal`.team_id 
`goal`.period_number 
`goal`.player_id 
`goal`.assist_player_id 

PERIOD_SUMMARY 
`period`.id 
`period`.game_id 
`period`.team_id 
`period`.number 
`period`.goals_scored  

В конце концов, я должен иметь записи для каждого периода играл в сводном период таблицы, независимо от того, был ли или не был забит гол. Эту таблицу нужно только инициализировать один раз, так как довольно легко добавить нулевые заполненные записи с помощью триггера при создании игры и запускать запросы на вставку/обновление для обновления таблицы period_summary.

Для меня также довольно легко сгруппировать все цели и инициализировать таблицу сводки периода с помощью SUM(), что у меня есть небольшая проблема, излагая эффективный способ «заполнить» любые периоды, которые «т есть гол, забитый с 0.

то, что я пытаюсь выяснить, если это проще/эффективнее:

  1. Написать триггер и предварительного заполнения всей period_summary таблицы с 0 заполненных значений , затем запустите запрос, который я уже знаю, чтобы обновить соответствующие записи за периоды, в которые были забиты голы.
  2. Используйте какой-либо другой метод (возможно, временную хранимую процедуру?), Которая будет только 0-заполнять записи, если в таблице целей нет соответствия.

ответ

3

У вас уже есть местозаполнитель. «Заполнитель для неизвестен данных» в SQL равен null.

Вам не нужно предварительно заполнять что-либо: либо у вас есть строка с некоторыми столбцами, имеющими неизвестное значение (null), либо у вас вообще нет строки, так что при выполнении внешнего соединения получается строка, это все null. В любом случае данные атрибута (по существу, не id) будут иметь значение null.

И агрегат sum() будет игнорировать нули.

Итак, скажем, что у вас do есть строка для игры (так как она запланирована заранее), но нет соответствующих строк для ее периодов (так как они еще не были воспроизведены). Тогда вы внешнее соединение игровой форме периода (внешней, так что вы включили обе игры с и игры без, период данные):

select a.*, sum(b.goals_scored) 
from game a left outer join period b on (b.game_id = a.id) 
group by a.id; 

Это показывает вам общие цели (для обеих команд) по игре;

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

select a.*, sum(b.goals_scored) 
from game a join period b on (b.game_id = a.id) 
group by a.id; 

Этот вид отфильтровывает неполные игры (при условии, что вы всегда добавить ранние периоды до более поздних):

create view complete_games as 
select a.* from games a 
where exists (select * from period b 
where b.game_id = a.id and b.number = a.number_of_periods) 

Используя эту точку зрения, мы можем только завершенные игры:

select a.*, sum(b.goals_scored) 
from complete_games a join period b on (b.game_id = a.id) 
group by a.id; 

Таким образом, нет необходимости предварительно заполнить, нет необходимости в триггере, самое главное, не нужно, чтобы добавить ложные данные (не требуя ноль голов, когда на самом деле период еще не играл), нет необходимости обновить с помощью правильных данных. Просто вставьте период, когда у вас есть данные для него.

+0

Извините, мое описание, возможно, было путаным в моем первоначальном вопросе. Обратите внимание, что сводная таблица еще не существует, и основной целью этого упражнения является инициализация этой таблицы данными. Мне нужно создать записи «0» для всех периодов, играемых в игре (в прошлом), где не было забито ни одного гола. – AvatarKava

+0

Да, на мой взгляд, вам не нужно «инициализировать»; просто добавьте записи, когда у вас есть данные после того, как период был воспроизведен. – tpdi

+0

Говоря, что я имел в виду заполнить таблицу данными из игр, которые уже были сыграны. – AvatarKava

0

ISTM, что вариант 1 явно проще: вы уже знаете, как увеличить bump счетчик, если вы можете доверять счетчику уже там. Предположим, что вы поедете с вариантом 2, не только сложнее заполнить недостающие нули (я полагаю, что это должно произойти в конце периода), вам также нужно будет найти способ запустить счетчик с 1, если нет предыдущего входа, и первый гол забит.

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

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

0

Знаете ли вы, что вы можете установить значение по умолчанию для столбца? С ключевым словом по умолчанию.

напр .:

CREATE TABLE Person ( возраст INT DEFAULT 0, имя VARCHAR (35) DEFAULT 'Bob')

Значение по умолчанию будет то, что вы хотите (0, например) вместо null.

Он не решает все, но это поможет.

Смежные вопросы