sql - 在 SQL 中搜索多列以获取值与存储在一列中

标签 sql database-design

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

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

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

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

例如:如果中奖号码是 01-02-03-04-05-06-07-08,我需要检查每一列以查看“07”是否在我的 lotto1 列中。

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

从 LOTTOTABLE 中选择 LottoTicketID,Count(LottoTicketID)
WHERE LottoNumber in (01,02,03,04,05,06,07,08)
GROUP BY LottoTicketID

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

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

最佳答案

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

  • 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 行对应的行。 table 。 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 BYGROUP_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显示票号的功能。

    关于sql - 在 SQL 中搜索多列以获取值与存储在一列中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11042843/

    相关文章:

    sql - 返回不符合 JOIN 的行

    c# - 什么是好的 Entity Framework 替代品

    sql - 判断月份是否包含条目

    sql - 如何为我的数据创建交叉引用表/查询?

    database - 用户表的最佳数据库设计(模型)

    PHP 多数组循环 WHERE 子句

    sql - 以编程方式获取数据库 w.r.t 关系中的所有表

    database - 如何标记表格的选定列以供显示

    mySQL 父、子模型和默认值

    mysql - 这是解决sql中最低性能问题的好方法