База данных результатов автоспорта (проблема дизайна) - PullRequest
0 голосов
/ 07 ноября 2018

Я создаю базу данных Motorsports, но у меня возникли некоторые трудности при разработке таблицы базы данных.

Проблема :

Для каждого раунда есть две расы, которые имеют разные системы очков. На данный момент я храню очки за ряд (от 20 до 30) за гонку, но это это отнимает много времени, и если я хочу изменить их в будущем, это будет головной болью, чтобы обновить их все.

Я мог бы сохранить как есть, но хотел бы лучшего решения.

Пример гонки 1 : (Позиция. Гонщик - Очки)

  1. Водитель 1 - 20
  2. Водитель 2 - 15
  3. Водитель 3 - 10
  4. Водитель 4 - 5

Пример гонки 2 : (Позиция. Гонщик - Очки)

  1. Водитель 1 - 10
  2. Водитель 2 - 8
  3. Водитель 3 - 6
  4. Водитель 4 - 3

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

Таблица, в которой должны храниться PointsSystemID, Position, Points.

У кого-нибудь есть идеи, как это сделать?

Примечание : я использую SQL Server 2014

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

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

Создание базовых таблиц.

CREATE TABLE DriverDetails ( DriverID int, DriverName varchar(100) ) ;
CREATE TABLE RaceDetails ( RaceID int, RaceDetails varchar(200) ) ;
CREATE TABLE PointSystems ( PointSystemID int, PositionID int, PointsAwarded int ) ;

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

Создание первичной таблицы результатов.

CREATE TABLE ref_RaceRounds ( 
    RaceRoundID int
  , RaceID int
  , DriverID int
  , DriverPositionID int
  , PointSystemID int 
) ;

Это таблица, которая по сути будет содержать результаты каждой расы. При необходимости может быть создана другая таблица типа RoundInfo для хранения информации о раундах, если это необходимо. Здесь также определяется PointSystem, который использовался для гонки. Если Гонка изменит систему очков позже, исторические точки будут сохранены. Если очки водителя будут скорректированы, когда Гонка меняет систему очков, то PointSystemID можно переместить в RaceDetails и JOIN можно настроить.

Заполните некоторые данные.

INSERT INTO DriverDetails (DriverID, DriverName)
VALUES (1,'Driver1'),(2,'Driver2'),(3,'Driver3'),(4,'Driver4'),(5,'SlowPoke') ;

INSERT INTO RaceDetails (RaceID, RaceDetails)
VALUES ( 1, 'Race1' ), ( 2, 'Race2' ) ;

/* This is assuming Driver Points are calculated by Race Position */
INSERT INTO PointSystems (PointSystemID, PositionID, PointsAwarded)
VALUES 
    ( 1, 1, 20 )
  , ( 1, 2, 15 )
  , ( 1, 3, 10 )
  , ( 1, 4,  5 )
  , ( 1, 5,  1 )
  , ( 2, 1, 10 )
  , ( 2, 2,  8 )
  , ( 2, 3,  6 )
  , ( 2, 4,  3 )
  , ( 2, 5,  1 )
;

/* Race Statistics by Driver */
INSERT INTO ref_RaceRounds ( RaceRoundID, RaceID, DriverID, DriverPositionID, PointSystemID)
VALUES
    (1,1,1,1,1)
  , (1,1,2,2,1)
  , (1,1,3,3,1)
  , (1,1,4,4,1)
  , (1,1,5,20,1)
  , (2,2,1,1,2)
  , (2,2,2,2,2)
  , (2,2,3,3,2)
  , (2,2,4,4,2)
  , (2,2,5,40,2)
;

При том, как я настраивал свои очки, если Водитель заканчивает в Позиции, у которой нет значения Очка, тогда этот Водитель получит null очков, которые могут быть преобразованы в 0 в конечном запросе. .

Теперь выполните запрос, соединив эти таблицы.

SELECT rrr.RaceRoundID
    , rd.RaceDetails
    , rrr.DriverID
    , dd.DriverName
    , rrr.DriverPositionID
    , ISNULL(ps.PointsAwarded,0) AS PointsAwarded
FROM ref_RaceRounds rrr
INNER JOIN DriverDetails dd ON rrr.DriverID = dd.DriverID
INNER JOIN RaceDetails rd ON rrr.RaceID = rd.RaceID
LEFT OUTER JOIN PointSystems ps ON rrr.PointSystemID = ps.PointSystemID
    AND rrr.DriverPositionID = ps.PositionID
    AND rrr.DriverID = dd.DriverID

Что дает:

RaceRoundID | RaceDetails | DriverID | DriverName | DriverPositionID | PointsAwarded
----------: | :---------- | -------: | :--------- | ---------------: | ------------:
          1 | Race1       |        1 | Driver1    |                1 |            20
          1 | Race1       |        2 | Driver2    |                2 |            15
          1 | Race1       |        3 | Driver3    |                3 |            10
          1 | Race1       |        4 | Driver4    |                4 |             5
          1 | Race1       |        5 | SlowPoke   |               20 |             0
          2 | Race2       |        1 | Driver1    |                1 |            10
          2 | Race2       |        2 | Driver2    |                2 |             8
          2 | Race2       |        3 | Driver3    |                3 |             6
          2 | Race2       |        4 | Driver4    |                4 |             3
          2 | Race2       |        5 | SlowPoke   |               40 |             0

Я использую ISNULL(ps.PointsAwarded,0) и LEFT OUTER JOIN, чтобы убедиться, что Водитель получает 0 баллов, если заканчивается в Позиции, которой не присвоено значение балла.

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

дБ <> скрипка здесь

ПРИМЕЧАНИЕ: Вы также можете легко добавить общее количество баллов к вашему запросу:

  • Добавить RaceDate к RaceDetails.

  • Добавить , SUM(ISNULL(ps.PointsAwarded,0)) OVER(PARTITION BY rrr.DriverID ORDER BY rd.RaceDate ROWS UNBOUNDED PRECEDING) AS PointsAwarded_RunningTotal к SELECT

https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=e477dbd2e978f685da59d548d1fe3b15

0 голосов
/ 07 ноября 2018

Вы можете создать именно ту таблицу, которую предлагаете в своем вопросе (PointsSystemID, Position, Points)

И в вашей таблице результатов замените Points на PointsSystemID.

Затем, чтобы рассчитать очки во время SELECT, просто объедините две таблицы на PointsSystemID и Position, и вы получите очки за каждого пилота в каждой гонке.

...