2

我正在设计一个系统,我应该在其中存储不同类型的彩票(结果+门票)。目前专注于 US Mega Millions 和 Singapore Pool Toto。它们都有相似的格式。

Mega Millions:从 1 到 56 的五个不同数字和从 1 到 46 的一个数字。多多:从 1 到 45 的 6 个数字

我需要想出一个优雅的数据库设计来存储用户票和相应的结果。我想了两种方法来解决它。

  1. 只需在 6 列中存储 6 个六个数字。或者
  2. 创建另一个具有球号和ticket_id的表(多对多)

我还需要存储结果的球号。

对于多多,如果您的号码匹配 4 个或更多中奖号码,您将中奖。对于百万富翁来说,也有类似的过程。

我正在寻找利弊或更好的解决方案?我做了很多研究和论文工作,但我仍然很困惑该走哪条路。

4

4 回答 4

2

两张桌子

tickets
    ball_number
    ticket_id

player
    player_id
    ticket_id

// optional
results
    ball_number
    lottery_id

使用两个表,您可以使用如下查询:

select ticket_id, count(ball_number) hits
from tickets 
where ball_number in (wn1, wn2, ...) // wn - winning number
group by ticket_id
having hits = x

当然,您可以从彩票结果表中获取中奖号码(或将它们存储在特殊票号下的 balls_table 中)。

准备统计数据也会更容易。和

select count(ticket_id)
from tickets 
group by ball_number

你可以很容易地看到哪些数字被选中最多。

您也可以使用像彩票号码这样的字段来缩小查询范围,因为它们中的大多数只涉及一张彩票。

一张桌子

为每个数字使用一个包含一列的表可能会使查询更加复杂。特别是,我相信,数字是排序的,除了一个(或两个)数字之外,还有奖品。比你可能需要比较1, 2, 3, ...的是2, 3, 4, ...哪个不像上面的查询那么简单。

一栏

将字符串中的所有条目存储在一列中违反了所有规范化做法,迫使您为大多数查询拆分列,并取消数据库执行的所有优化。与存储文本相比,存储数字所需的磁盘空间也更少。

于 2013-05-20T08:57:33.643 回答
1

由于这是一天一次的事情,我想我会以一种易于编辑、维护和可视化的方式存储数据。你的多对多方法会奏效。主要是,我希望很容易找到选择特定 ball_number 的用户。

users
  id
  name

drawings
  id
  type # Mega Millions or Singapore (maybe subclass Drawing) 
  drawing_on

wining_picks
  drawing_id
  ball_number

ticket
  drawing_id
  user_id
  correct_count

picks  
  id
  ticket_id
  ball_number

输入数字后,查找在绘图中选择特定数字的所有 user_id

按日期获取图纸

drawing = Drawing.find_by_drawing_on(drawing_date)

通过 ball_number 和绘图获取用户。

picked_1 = User.picked(1,drawing)
picked_2 = User.picked(2,drawing)
picked_3 = User.picked(3,drawing)

这是用户的范围

class User < ActiveRecord::Base

  def self.picked(ball_number, drawing)
    joins(:tickets => :picks).where(:picks => {:ball_number => ball_number}, :tickets => {:drawing_id => drawing.id})
  end

end

然后进行快速数组交叉以获得正确选择 3、4、5、6 的 user_id。您将遍历中奖号码以获取排列。

例如,如果中奖号码是 3,8,21,24,27,44

some_3_correct_winner_ids = picked_3 & picked_8 & picked_21  # Array intersection

对于每个获胜者 - 用正确的计数更新彩票。

我可能会单独存储获胜者,但是在正确计数上有一个索引,并且门票中没有太多数据,现在这可能没问题。

于 2013-05-20T17:13:14.840 回答
0

我只是使用约定将它们连接起来并将它们存储在一列中。

'10~20~30~40~50~!60' 之类的东西〜分隔数字!表示特殊号码(强力球等)

如果您确实需要将结果放在列中,请使用 sql 表值函数拆分结果。

于 2013-05-20T08:36:40.960 回答
0

首先,让我说我是 Oracle 人,而不是 MySQL 人。

其次,我通常会说要采用标准化设计,但我很想在这里想一个非常规的替代方案,我会在这里提出意见。

您如何将其非规范化到对所有数字选择使用一列的程度?

ticket_id      integer
nums           bit(56)
special_number integer

这将是一个非常紧凑的表示,您也许可以使用按位运算来找到获胜者或潜在的获胜者。

不知道这是否可行……开放评论。

于 2013-05-21T11:07:11.987 回答