Как наиболее эффективно организовать эти таблицы + строки?- MySQL
-
12-12-2019 - |
Вопрос
Я собираюсь проводить лотереи на своем веб-сайте, поэтому нужно где-то хранить билеты и номера.У меня обязательно будет столик под названием tickets
в котором каждая строка будет иметь свой собственный идентификатор билета, связанный с ним идентификатор лотереи и всю другую информацию (например, идентификатор пользователя, которому он принадлежит).
Однако мой вопрос в том, стоит ли мне создавать еще одно поле в tickets
для хранения номеров, выбранных в билете.Невозможно создать несколько полей, таких как number1
, number2
и т. д., поскольку в каждой лотерее будут разные типы билетов (т. е. lottery1
может попросить вас выбрать 4 номера, и lottery2
может попросить вас выбрать 6).
Поэтому я могу создать новое поле VARCHAR или TEXT для приема номеров билетов, разделенных запятыми, т. е.: 1,2,3,4,5,6
или создайте еще одну новую таблицу под названием numbers
где каждая строка будет иметь идентификатор билета и номер, связанный с ним.Однако я не уверен, что этот метод очень эффективен, поскольку для одного билета из 6 номеров должна быть 1 строка в tickets
таблице и 6 строк в numbers
стол.
Какой из этих вариантов наиболее эффективен?Или есть еще лучший способ сделать это, чем этот?Помните, что в конце лотереи код должен будет циклически просмотреть каждый билет, чтобы проверить, выиграли ли они, поэтому вариант 2 может оказаться слишком ресурсоемким.
Решение
В дальнейшем «Билет[Номер]» следует понимать как «Выбранный Набор лотерейных номеров».Помните, что Set(a,b,c)
равно Set(c,b,a)
.
Я бы сделал это так:
Purchase
-PersonID // associate Person (one person can have many purchases)
-TicketID // associate Ticket (a purchase is for one "ticket",
// which can be purchased many times)
-DisplayTicketNumber // for Human Display
Ticket
-TicketNumber
То есть, Purchase:M-1:Ticket
А DisplayTicketNumber
это число, выбранное пользователем, например.«3,1,2», тогда как, с другой стороны, TicketNumber
— это нормализованный номер билета, в котором сначала ставятся небольшие значения.Окончательная форма, таким образом, min,..,max
или похожие.То есть любое количество DisplayTicketNumbers
которые имеют одинаковый набор значений (в любом порядке), будут иметь одинаковый TicketNumber
:
DisplayTicketNumber TicketNumber
1,2,3 1,2,3
2,3,1 1,2,3
3,2,1 1,2,3
3,2,1,4 1,2,3,4 .. and etc
Затем поместите индекс на TicketNumber
так что просто WHERE TicketNumber = @normalizedTicketNumber
будет очень быстрый индекс.
Я бы даже сказал, что это приемлемо нормализованный дизайн, а номер билета (вместе, скажем, с номером лотереи) образует ключ.Мои аргументы в пользу этого таковы:
TicketNumber — это непрозрачное значение который однозначно идентифицирует Билет (для каждого Розыгрыша).Не нужно «знать детали» внутри модели БД.(В некоторых случаях может возникнуть необходимость, но не здесь.)
DisplayTicketNumber — это артефакт, введенный пользователем;однако несколько DisplayTicketNumbers могут представлять один и тот же TicketNumber.Хотя это делает представляют собой возможное «дублирование», важно понимать, что это Дружественный дисплей значение, которое представляет собой список (который содержит больше информации, чем набор) выбранных чисел.
В таком случае я бы сделал
DisplayTicketNumber
(иTicketNumber
) неизменяем с триггерами, так что после создания сюда не могут быть внесены несоответствия базы данных.Если FK может быть вычислен, то ограничение между DisplayTicketNumber и TicketNumber может быть реализовано без неизменяемости.
(Я опустил некоторые детали, например наличие разных номеров билетов для разных розыгрышей и т. д.Я также показываю TicketId
за ФК, но я еще и намекнул, что RaffleId,TicketNumber
является приемлемым [несуррогатным] ключом.)
Также таблица билетов мог быть устранены:поскольку очень немногие наборы номеров лотереи будут общими, поэтому, если нет дополнительной связанной информации о билете, ее удаление может быть приемлемый денормализация.Одним из преимуществ этого является то, что TicketNumber
можно было бы переместить в Purchase
стол, а затем превратился в вычисляемый столбец (который все еще индексируется), который нормализовал стоимость билета.
И, если MySQL позволяет использовать вычисляемый столбец в FK, а затем использовать отношение PK(Ticket.TicketNumber)
-> FK(Purchase.TicketNumber)
, где Purchase.TicketNumber
вычисляется, мог использоваться для повышения целостности модели без устранения таблицы Ticket.(Однако я не использую MySQL, поэтому не могу сказать, жизнеспособно это или нет.)
Приятного кодирования.
Другие советы
Я бы использовал второй вариант, когда вы создаете новую таблицу, называемую числами, и с ней связаны числа.
Но я бы также добавил поле в таблицу билетов, где вы указываете количество номеров, которые можно выбрать, и условие, в котором вы проверяете, меньше ли количество номеров, вставленных с помощью этого билета (используя COUNT в запросе), количество чисел, которые можно выбрать, а затем вставить.