Designing a database - Games played table - database

I have pretty basic question. I'm designing a database to keep track of the chess games being played among certain group of individuals. I am thinking of creating one player table which will hold the details of each individual player. The primary key would be player ID.
My question is about associating games with players.
My initial thought is to create a games table. Each record in it will be a game, it will have 2 columns for players(player ids) who played it and third column will be a winner( or draw ).
What is the best way to design it? Should third columns value be a player id or I can just specify 1 if player in first column has won the game otherwise 0. How do I handle draw case? Do I insert some keyword?
I'd also like to know if there is some completely other way of designing this database.

Sublime, there are several ways you could define the structure of this database. Which design you ultimately choose depends on the performance expectations and the ultimate maintenance requirements of your database. I would recommend reading up on normalization which will give you some insights into the pros and cons of designing your tables in various ways.
To answer your specific question, I would:
Make a games table that consisted of the fields:
Game ID (primary key)
Player 1 ID (Foreign key to your players table)
Player 2 ID (Foreign key to your players table)
Game result
Important points to note here:
I included a game id primary key to uniquely identify one game from another. Without this, you will not be able to differentiate multiple games played by the same players. You may or may not require this in your implementation.
Game result could contain different sets of values based on your method of extracting the data into some meaningful representation. For example, some possibilities are to:
Have game result equal player id or 0 or -1 to indicate a draw. Least preferred, in my opinion, since this results in a consistency problem in the data that the field represents.
Have game result equal a pre-defined list of possible values (1 = Player 1 won, 2 = Player 2 won, 3 = Draw, 4 = Still in progress, etc). The possible values could be it's own table. This approach requires more extensive query planning.
You could also structure your data to consist of:
A players table - Player information
A games table - Game information
A results table - Game results information
In this setup, your games table would include only game id and the players id's. The results table would include the game id and the result of the game using one of the above solutions for identifying the winner.

Here are my views:
I don't like the idea of having the two columns 'player 1' and 'player 2'. When trying to get a list of all games 'Jeff' has played, you will have to check both 'player 1' and 'player 2' columns for his Id.
You could fix the above point by implementing a 'GamePlay' type of table, which has separate rows for each player. This way each player has their own outcome and are are held in a single column for easy querying.
A separate table for for possible outcomes would be tidy.
I've drafted up an example below
GameResult - Reference table for game results
GameResultId | Desc
01 | Won
02 | Lost
03 | Drew
Game - This is the game table, lists games. Can have details of location, date, time ect.
GameId | StartTime | Location | Ect
01 | 13:00 | Park | ect..
GamePlay - Have a row for each member-game interaction.
GamePlayId | GameId | PlayerId | GameResultId
01 | 01 | 01 | 01
02 | 01 | 02 | 02
This way, you can query by your players a lot easier.
(Such as getting a list of all players who have won a match)
SELECT
p.PlayerName
FROM
Player p
INNER JOIN GapePlay gp
ON p.PlayerId = gp.PlayerId
WHERE gp.GameresultId = 1
You could still easy query by game too
SELECT
gp.GameId
, p.Name
, gr.Desc
FROM
GamePlay gp
INNER JOIN Player p
ON gp.PlayerId = p.PlayerId
INNER JOIN GameResult gr
ON gp.GameresultId = gr.GameResultId
WHERE
GamePlayId = 01

Related

Many to Many Database Relationship Design - to enable Word Clouds

I'm relatively new to database design and struggling to introduce a many-to-many relationship in a SSAS Tabular model.
I have some 'WordGroup' performance data in one table, like so;
WordGroup | IndexedVolume
Dining | 1,000
Sports | 2,000
Movies | 1,600
... and so on
Then I have 'Words' contained within these 'WordGroups' sitting in another category table, like so;
WordGroup | Word
Dining | Restaurant
Dining | Food
Dining | Dinner
Sports | Football
Sports | Basketball
... and so on
I can't see Performance data (IndexedVolume) by 'Word' detail - only by the 'WordGroup' that it is contained within. For example above, I can't look at 'Football' IndexedVolume on it's own, I can only choose the 'Sports' WordGroup that contains Football.
However, when analysing by 'WordGroup' I would still like users to understand what 'Words' are included (ideally in a Word Cloud Visualisation). Therefore, I wanted to develop a relationship between these two tables, so when someone chooses a Word Group (or multiple) we can return the Words that are contained within the Word Group(s) - i.e. below.
User selects Dining WordGroup
<<<Word Cloud or Flat Table would show Words below>>>
Restaurant
Food
Dinner
I looked at Concatenate / Strings etc, but was deterred as the detail here is much more complex and each WordGroup may contain 10+ Words, with translations.
Any advice would be greatly appreciated!
If analizing by WordGroup is an obligatory requirement, you sholud use these tables:
The many-to-many aplies beacuse your words may be conected to one or more groups, e.g. tree is conected to enviroment, forest, etc.
and obviously one word_group is conected to many words.
To see performance data by Word use :
select w.idword , w.name, sum(wg.index_volume)
from word w
left join word_group_has_word wgw
on w.idword=wgw.word_id
left join word_group wg
on wg.idword_group=wgw.word_group_id
group by w.idword
So you will see the sum of all the index volume of all the group_words conected to the words. ANd if you wanna see the words conected to the word groups use:
select distinct w.idword , w.name
from word w
left join word_group_has_word wgw
on w.idword=wgw.word_id
where wgw.word_group_id in [listWordGroupsId]

Designing a schedule in a sports database

I will try to be as specific as possible, but I am having trouble conceptualizing the problem. As a hobby I am trying to design a NFL database that takes raw statistics and stores it for future evaluation for fantasy league analysis. One of the primary things I want to see is if certain players/teams perform well against specific teams and which defenses are suspect to either pass/run. The issue I am having is trying to design the schedule/event table. My current model is as follows.
TEAMS
TeamID, Team
SCHEDULE
ScheduleID, TeamID, OpponentID, Season, Week, Home_Away, PointsFor, PointsAgainst
In this scenario I will be duplicating every game, but when I use an event table where I use TeamAway and TeamHome I find my queries impossible to run since I have to query both AwayTeam and HomeTeam to find the event for a specific team.
In general though I cannot get a query to work where I have two relationships from a table back to one table, even in the schedule table my query does not work.
I have also considered dropping the team table and just storing NE, PIT, etc. for the Team and Opponent fields so I do not have to deal with the cross-relationships back to the team table.
How can I design this so I am not running queries for TeamID = OpponentID AND TeamID?
I am doing this in MS Access.
Edit
The issue I am having is when I query two table: Team (TeamID, Team) and Event(TeamHomeID, TeamAwayID), that had relationships built between the TeamID - TeamHomeID, and TeamID - TeamWayID I had issues building the query in ms Access.
The SQL would look something like:
SELECT Teams.ID, Teams.Team, Event.HomeTeam
FROM Teams INNER JOIN (Event INNER JOIN Result ON Event.ID = Result.EventID)
ON (Teams.ID = Result.LosingTeamID) AND (Teams.ID = Result.WinningTeamID)
AND (Teams.Team = Event.AwayTeam) AND (Teams.Team = Event.HomeTeam);
It was looking for teams that had IDs of both the losing team and the winning team (which does not exist).
I think I might have fixed this problem. I didn't realize the Relationships in database design are only default, and that within the Query builder I could change the joins on which a particular query is built. I discovered this by deleting all the AND portions of the SQL statement returned, and was able to return the name of all winnings teams.
This is an interesting concept - and good practice.
First off - it sounds like you need to narrow down exactly what kind of data you want so you know what to store. I mean, hell, what about storing the weather conditions?
I would keep Team, but I would also add City (because Teams could switch cities).
I would keep Games (Schedule) with columns GameID, HomeTeamID, AwayTeamID, ScheduleDate.
I would have another table Results with columns ResultID, GameID, WinningTeamID, LosingTeamID, Draw (Y/N).
Data could look like
TeamID | TeamName | City
------------------------
1 | PATS | NE
------------------------
2 | PACKERS | GB
GameID | HomeTeamID | AwayTeamID | ScheduleDate | Preseason
-----------------------------------------------------------
1 | 1 | 2 | 1/1/2016 | N
ResultID | GameID | WinningTeamID | LosingTeamID | Draw
------------------------------------------------------------
1 | 1 | 1 | 2 | N
Given that, you could pretty easily give any W/L/D for any Scheduled Game and date, you could easily SUM a Teams wins, their wins when they were home, away, during preseason or regular season, their wins against a particular team, etc.
I guess if you wanted to get really technical you could even create a Season table that stores SeasonID, StartDate, EndDate. This would just make sure you were 100% able to tell what games were played in which season (between what dates) and from there you could infer weather statistics, whether or not a player was out during that time frame, etc.

Database, table inheritance?

This is about database structure. (inheritance)
Say you have Place and Restaurant and Cafe are two subtypes of place.
You can create a Place table to hold a common info of the subtypes.
and create a foreign key to connect to Retaurant or Cafe instance.
or
You can duplicate stuff in Restaurant and Cafe
I'm coming from Django background, and many seem to prefer #2 over #1.
Is there a compelling scenario where you should pick one over another?
One scenario I think I need the #1 is when you are going to sort all Places collectively. (Can we use #2 for this?)
I think I would go for #2, as you don't have to think about relations and foreign keys and the model itself is complete, so you could just copy the database and use it for something else.
Further you just have to query one table instead of two.
If you need to sort Restaurant and Cafe, you can use the SQL UNION Operator.
Let's assume you have these two simple tables:
restaurant
id | name | likes
-------------------------
1 | Steakhouse | 5
2 | Italian Food | 3
cafe
id | name | likes
--------------------------
1 | Starbucks | 0
You can query them using the UNION operator like this:
SELECT * FROM cafe
UNION
SELECT * FROM restaurant
ORDER BY likes DESC
Which will return a list of cafes and restaurants ordered by likes as if they are coming from the same table.

Database design for voting

I am implementing a voting feature to allow users to vote for their favourite images. They are able to vote for only 3 images. Nothing more or less. Therefore, I am using checkboxes to do validation for it. I need to store these votes in my database.
Here is what i have so far :
|voteID | name| emailAddress| ICNo |imageID
(where imageID is a foreign key to the Images table)
I'm still learning about database systems and I feel like this isn't a good database design considering some of the fields like email address and IC Number have to be repeated.
For example,
|voteID | name| emailAddress | ICNo | imageID
1 BG email#example.com G822A28A 10
2 BG email#example.com G822A28A 11
3 BG email#example.com G822A28A 12
4 MO email2#example.com G111283Z 10
You have three "things" in your system - images, people, and votes.
An image can have multiple votes (from different people), and a person can have multiple votes (for different images).
One way to represent this in a diagram is as follows:
So you store information about a person in one place (the Person table), about Images in one place (the Images table), and Votes in one place. The "chicken feet" relationships between them show that one person can have many votes, and one image can have many votes. ("Many" meaning "more than one").

How do I create nested categories in a Database?

I am making a videos website where categories will be nested:
e.g. Programming-> C Language - > MIT Videos -> Video 1
Programming -> C Language -> Stanford Video - > Video 1
Programming -> Python -> Video 1
These categories and sub-categories will be created by users on the fly. I will need to show them as people create them in the form of a navigable menu, so that people can browse the collection easily.
Could someone please help me with how I can go about creating such a database?
Make a categories table with the following fields:
CategoryID - Integer
CategoryName - String/Varchar/Whatever
ParentID - Integer
Your ParentID will then reference back to the CategoryID of its parent.
Example:
CategoryID CategoryName ParentID
---------------------------------
1 Dog NULL
2 Cat NULL
3 Poodle 1
4 Dachsund 1
5 Persian 2
6 Toy Poodle 3
Quassnoi said :
You should use either nested sets or parent-child models.
I used to implement both of them. What I could say is:
Use the nested set architecture if your categories table doesn't change often, because on a select clause it's fast and with only one request you can get the whole branch of the hierarchy for a given entry. But on a insert or update clause it takes more time than a parent child model to update the left and right (or lower and upper in the example below) fields.
Another point, quite trivial I must admit, but:
It's very difficult to change the hierarchy by hand directly in the database (It could happen during the development). So, be sure to implement first an interface to play with the nested set (changing parent node, move a branch node, deleting a node or the whole branch etc.)
Here are two articles on the subject:
Storing Hierarchical Data in a Database
Managing Hierarchical Data in MySQL
Last thing, I didn't try it, but I read somewhere that you can have more than one tree in a nested set table, I mean several roots.
You should use either nested sets or parent-child models.
Parent-child:
typeid parent name
1 0 Buyers
2 0 Sellers
3 0 Referee
4 1 Electrical
5 1 Mechanic
SELECT *
FROM mytable
WHERE group IN
(
SELECT typeid
FROM group_types
START WITH
typeid = 1
CONNECT BY
parent = PRIOR typeid
)
will select all buyers in Oracle.
Nested sets:
typeid lower upper Name
1 1 2 Buyers
2 3 3 Sellers
3 4 4 Referee
4 1 1 Electrical
5 2 2 Mechanic
SELECT *
FROM group_types
JOIN mytable
ON group BETWEEN lower AND upper
WHERE typeid = 1
will select all buyers in any database.
See this answer for more detail.
Nested sets is more easy to query, but it's harder to update and harder to build a tree structure.
From the example in your question it looks like you'd want it to be possible for a given category to have multiple parents (e.g., "MIT Videos -> Video 1 Programming" as well as "Video -> Video 1 Programming"), in which case simply adding a ParentID column would not be sufficient.
I would recommend creating two tables: a simple Categories table with CategoryID and CategoryName columns, and a separate CategoryRelationships table with ParentCategoryID and ChildCategoryID columns. This way you can specify as many parent-child relationships as you want for any particular category. It would even be possible using this model to have a dual relationship where two categories are each other's parent and child simultaneously. (Off the top of my head, I can't think of a great use for this scenario, but at least it illustrates how flexible the model is.)
What you need is a basic parent-child relationship:
Category (ID: int, ParentID: nullable int, Name: nvarchar(1000))
A better way to store the parent_id of the table is to have it nested within the ID
e.g
100000 Programming
110000 C Language
111000 Video 1 Programming
111100 C Language
111110 Stanford Video
etc..so all you need it a script to process the ID such that the first digit represents the top level category and so on as you go deeper down the hierarchy

Resources