3

I need to store lotto numbers in a SQL database. There are 8 separate numbers that make up the lotto number.

EX: 07-12-34-40-59-80-88-89

I first thought to store this data in a single row with columns named lotto1 - lotto8. This makes sense because lotto numbers are always displayed low to high, and users will need to see the stored lotto numbers. Writing a select statement would be trivial.

I also need to see how many of the lotto numbers are winners. To do this I need to search for each winning number in every single column.

EX: If the winning numbers were 01-02-03-04-05-06-07-08, I would need to check every column to see "07" is in my lotto1 column.

Checking for winners would be easier if all lotto numbers were stored in a 1 column, and they had a LottoTicketID to associate the 8 rows of data with 1 ticket. When checking for winners, I don't need to say which specific numbers/positions were matches, just how many matches there were.

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

Storing this way would cause problems because I would need to write 7 joins just to display the numbers.

Can someone suggest a way to store this data so that I can: 1. Quickly displayed the lotto numbers/entires 2. Check for winners

4

4 に答える 4

3

おそらくこれに取り組みたいと思う方法は、宝くじに関する情報を格納する 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  
    

1:N の識別関係を介してフィールド上の 2 つを接続し、id各宝くじに対応する 8 つの行がlottery_ticket_numbersテーブルにあるようにします。この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 に同様の機能があるかどうかはわかりません。

ここで、宝くじの実際の当選番号に関するデータも保存したいと思うでしょう。このために、ほぼ同じ方法で 2 つのテーブルも使用します。1 つは宝くじ番号用で、もう 1 つは対応する番号用です。

  • 当選番号:

    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()ます。


ここで、列ベースのアプローチ (当選番号とチケット番号を 1 つの行として格納しますが、各番号を格納する 8 つの列を使用する) を使用する場合に行う必要があることを見てみましょう。

スキーマを仮定すると:

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あなたが私に尋ねるとしたら、それは非常に多くのことです...!!!

このアプローチの利点はGROUP_CONCAT、チケット番号を表示するために MySQL 固有の関数が必要ないことです。

于 2012-06-15T20:21:50.797 に答える
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 に答える