The way you'll probably want to tackle this is to have two tables to store information about lottery tickets:
lottery_tickets: To store information about each individual lottery ticket:
lottery_tickets
----------------------
id [PK]
first_name
last_name
date_given
...
lottery_ticket_numbers: To store that corresponding lottery ticket's numbers:
lottery_ticket_numbers
----------------------
id [PK](FK)
number [PK]
position
Connect the two on the id
field via a 1:N identifying relationship, and have each lottery ticket have 8 corresponding rows in the lottery_ticket_numbers
table. The position
field will keep track of each numbers' position (1-8) in the whole string of numbers.
What this will allow you to do is easily figure out the winning lottery tickets by JOINing the tables together and narrowing it down to which lottery tickets have ALL the matching numbers:
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
The result set will look something like this:
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
Note:
- If you are using MySQL, the
GROUP_CONCAT()
function consolidates the winning tickets' numbers in the format XX-XX-XX-XX-XX-XX-XX-XX with numbers in their original order that the person got it. If you're not using MySQL, I'm not sure if similar function exists in other DBMSs.
Now you'll probably want to store data about the actual winning lottery numbers as well. For this, you will also utilize two tables in much the same way: one for the lottery number and another for its corresponding numbers:
To query for the winning tickets:
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
Nearly the same as the previous query, except that now the number list is a result set from a subquery.
Displaying the winning lottery numbers is simple. Ex:
Retrieve all winning numbers and their pull date; displaying their number string as numbers in ascending order, and ordering by the most recent pulled number:
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
Note that when you insert winning numbers, you won't have to worry at all about the order of the numbers which you insert. Since they are always displayed in ascending order, the ORDER BY
in the GROUP_CONCAT()
takes care of that for you.
Now let's take a look at what you'll have to do if you use the column-based approach (storing winning numbers and ticket numbers as single row but with eight columns housing each number):
Assuming the schema:
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)
Find all winning tickets for a given lottery number:
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>
That's one heck of a lot of IN
s if you were to ask me...!!!
The advantage of this approach is that you wouldn't need the MySQL-specific GROUP_CONCAT
function to display the ticket numbers.