3

我需要将乐透号码存储在 SQL 数据库中。有 8 个独立的号码组成乐透号码。

例如:07-12-34-40-59-80-88-89

我首先想到将这些数据存储在一个名为 lotto1 - lotto8 的列中。这是有道理的,因为乐透号码总是从低到高显示,用户需要查看存储的乐透号码。编写一个 select 语句将是微不足道的。

我还需要看看有多少乐透号码是中奖者。为此,我需要在每一列中搜索每个中奖号码。

例如:如果中奖号码是 01-02-03-04-05-06-07-08,我需要检查每一列才能看到“07”在我的乐透 1 列中。

如果所有乐透号码都存储在 1 列中,并且他们有一个 LottoTicketID 将 8 行数据与 1 张彩票相关联,则检查中奖者会更容易。在检查获胜者时,我不需要说匹配的具体数字/位置,只需要说明有多少匹配。

SELECT LottoTicketID,Count(LottoTicketID) from LOTTOTABLE WHERE LottoNumber in (01,02,03,04,05,06,07,08) GROUP BY LottoTicketID

以这种方式存储会导致问题,因为我需要编写 7 个连接来显示数字。

有人可以建议一种存储这些数据的方法,以便我可以: 1. 快速显示乐透号码/全部 2. 检查中奖者

4

4 回答 4

3

您可能想要解决这个问题的方法是有两个表来存储有关彩票的信息:

  • lottery_tickets:存储有关每张彩票的信息:

    lottery_tickets
    ----------------------
    id [PK]
    first_name
    last_name
    date_given
    ...
    
  • lottery_ticket_numbers:存储相应的彩票号码:

    lottery_ticket_numbers
    ----------------------
    id        [PK](FK)
    number    [PK]
    position  
    

字段上两者id通过1:N识别关系连接,每张彩票在lottery_ticket_numbers表中有8行对应。该position字段将跟踪整个数字字符串中每个数字的位置 (1-8)。

这将允许您通过将表格连接在一起并将范围缩小到具有所有匹配号码的彩票来轻松找出中奖彩票:

SELECT
    a.*,
    GROUP_CONCAT(b.number ORDER BY position SEPARATOR '-') AS lottery_number
FROM
    lottery_tickets a
INNER JOIN
    lottery_ticket_numbers b ON a.id = b.id
WHERE
    b.number IN (07,12,34,40,59,80,88,89)
GROUP BY 
    a.id
HAVING 
    COUNT(b.number) = 8

结果集将如下所示:

id   |   first_name   |   last_name   |   date_given   |   lottery_number
--------------------------------------------------------------------------------
823  |   Zane         |   Bien        |   2012-01-01   |   34-80-07-89-12-40-59-88
2321 |   Jeff         |   Clark       |   2012-01-14   |   59-07-88-40-12-34-80-89

注意

  • 如果您使用的是 MySQL,该GROUP_CONCAT()函数将 XX-XX-XX-XX-XX-XX-XX-XX 格式的中奖彩票号码与该人获得的原始号码中的号码合并。如果您不使用 MySQL,我不确定其他 DBMS 中是否存在类似功能。

现在您可能还想存储有关实际中奖彩票号码的数据。为此,您还将几乎相同的方式使用两张表:一张用于彩票号码,另一张用于对应的号码:

  • 获胜号码

    winning_numbers
    ----------------------
    id [PK]
    date_pulled
    
  • 获奖号码号码

    winning_numbers_numbers
    ----------------------
    id     [PK](FK)
    number [PK]
    

查询中奖彩票:

SELECT
    a.*,
    GROUP_CONCAT(b.number ORDER BY position SEPARATOR '-') AS lottery_number
FROM
    lottery_tickets a
INNER JOIN
    lottery_ticket_numbers b ON a.id = b.id
WHERE
    b.number IN
    (
        SELECT number
        FROM winning_numbers_numbers
        WHERE id = <id of a particular lottery number>
    )
GROUP BY 
    a.id
HAVING 
    COUNT(b.number) = 8

与前面的查询几乎相同,只是现在数字列表是来自子查询的结果集。

显示中奖彩票号码很简单。前任:

检索所有中奖号码及其开奖日期;将他们的数字字符串显示为按升序排列的数字,并按最近提取的数字排序:

SELECT
    GROUP_CONCAT(b.number ORDER BY b.number SEPARATOR '-') AS winning_number,
    a.date_pulled
FROM
    winning_numbers a
INNER JOIN
    winning_numbers_numbers b ON a.id = b.id
GROUP BY 
    a.id
ORDER BY
    a.date_pulled DESC

请注意,当您插入中奖号码时,您完全不必担心您插入的号码的顺序。由于它们始终按升序显示,因此ORDER BYinGROUP_CONCAT()会为您处理。


现在让我们看看如果您使用基于列的方法(将中奖号码和彩票号码存储为单行,但每个号码有八列),您将需要做什么:

假设架构:

winning_numbers(id, date_pulled, n1, n2, n3, n4, n5, n6, n7, n8)

ticket_numbers(id, fname, lname, date_given, n1, n2, n3, n4, n5, n6, n7, n8)

查找给定彩票号码的所有中奖彩票

SELECT
    a.*
FROM 
    ticket_numbers a
INNER JOIN
    winning_numbers b ON
        a.n1 IN (b.n1, b.n2, b.n3, b.n4, b.n5, b.n6, b.n7, b.n8) AND
        a.n2 IN (b.n1, b.n2, b.n3, b.n4, b.n5, b.n6, b.n7, b.n8) AND
        a.n3 IN (b.n1, b.n2, b.n3, b.n4, b.n5, b.n6, b.n7, b.n8) AND
        a.n4 IN (b.n1, b.n2, b.n3, b.n4, b.n5, b.n6, b.n7, b.n8) AND
        a.n5 IN (b.n1, b.n2, b.n3, b.n4, b.n5, b.n6, b.n7, b.n8) AND
        a.n6 IN (b.n1, b.n2, b.n3, b.n4, b.n5, b.n6, b.n7, b.n8) AND
        a.n7 IN (b.n1, b.n2, b.n3, b.n4, b.n5, b.n6, b.n7, b.n8) AND
        a.n8 IN (b.n1, b.n2, b.n3, b.n4, b.n5, b.n6, b.n7, b.n8) AND
        b.id = <winning number id>

IN如果你要问我,那真是一大堆……!!!

这种方法的优点是您不需要特定于 MySQL 的GROUP_CONCAT函数来显示票号。

于 2012-06-15T20:21:50.797 回答
1

以这种方式存储会导致问题,因为我需要编写 7 个连接来显示数字。

唯一需要进行 7 次连接才能显示所有数字的情况是,如果您需要它们在单行上。如果您在数据库之外处理这些(甚至使用存储过程),将它们收集成可读格式是微不足道的。

如果您的数据库支持,您可能拥有的另一个选择是将所有数字放在单个数组类型的列中或使用某种多行分析函数。你总是可以只写一个视图来解决这个问题。

于 2012-06-14T23:52:49.407 回答
1

为什么需要编写 7 个连接来显示数字?你可以这样写:

SELECT LottoNumber FROM LOTTOTABLE
WHERE LottoTicketID=n
ORDER BY LottoNumber

您可以使用您已经建议的查询来检查它们:

SELECT LottoTicketID, Count(LottoTicketID) 
FROM LOTTOTABLE 
WHERE LottoNumber in (01,02,03,04,05,06,07,08) 
GROUP BY LottoTicketID

您还可以使用以下方法将此列表限制为仅获奖者:

HAVING Count(LottoTicketID) = 8

您还可以将乐透号码存储为 TINYINT 以减小数据库大小。

于 2012-06-15T00:00:13.377 回答
0

正如您所提到的,将数字存储在单列中有很多优点。如果唯一剩下的问题是将它们一起显示的复杂性,那么有很多可能性可以干净而轻松地做到这一点 - 而且它经常被忽视,所以这个问题经常被问到。

对于几种 SQL 风格以及一些独立于平台的选项,这里处理得很好: 将许多行连接成一个文本字符串?

于 2012-06-15T01:05:38.127 回答