我将在我的网站上运行彩票,因此需要在某处存储门票和号码。我肯定会有一个名为tickets
的表,其中每一行都有自己的票证ID,相关的彩票ID和所有其他信息(例如它所属的用户的id)。
但是,我的问题是我是否应该在tickets
建立另一个领域以保留票上所选的数字。创建多个字段(例如number1
,number2
等)不是一个选项,因为每个彩票都会有不同类型的门票(即lottery1
可能会要求您选择4个数字,而lottery2
可能会要求您选择6个)。
因此,我可以创建一个新字段,即VARCHAR或TEXT,以接受以逗号分隔的票号,即:1,2,3,4,5,6
或创建另一个名为numbers
的新表,其中每一行都有与之关联的票证ID和号码。但是我不确定这种方法是否非常有效,因为只有一个6个数字的票证,tickets
表中需要有1行,numbers
表中需要6行。
哪些选项最有效?或者有更好的方法来做到这一点?请记住,在抽奖结束时,代码需要循环每张票以检查他们是否已经获胜 - 因此选项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
(和TicketNumber
)使用触发器不可变,这样在创建之后,不会在这里引入数据库不一致。
如果可以计算FK,则可以强制执行DisplayTicketNumber和TicketNumber之间的约束而不具有不变性。(我省略了各种细节,例如为不同的莱佛士提供不同的TicketNumbers等。我还为FK展示了TicketId
,但我也暗示RaffleId,TicketNumber
是可接受的[非代理]密钥。)
此外,票证表可以被删除:因为很少有彩票号码集将被共享,因此,如果没有额外的关联票证信息,则删除它可能是可接受的非规范化。这样做的一个优点是TicketNumber
可以移动到Purchase
表中,然后变成一个计算列(仍然被索引),以标准化Ticket值。
并且,如果MySQL允许在FK中使用计算列,则使用关系PK(Ticket.TicketNumber)
- > FK(Purchase.TicketNumber)
(其中计算Purchase.TicketNumber
)可以用于增加模型完整性而不消除Ticket表。 (但我不使用MySQL,所以我不能说这是否可行。)
快乐的编码。
我会使用第二个选项来制作新表,称为数字,并且您有与之关联的数字。
但是我还会在故障单表中添加一个字段,您可以在其中指明可以选择的数字量,以及检查使用该故障单插入的数字量(在查询中使用COUNT)是否小于的条件可以选择的数字量,然后插入。