Correct Normalization for Players to Match - sql

Each match has 14 players.
I currently have it so that I enter 14 entries into the match table like so:
matchID bookingID playerID
1 1 1
1 1 2
1 1 3
1 1 4
etc.
Would this be okay or would it be more acceptable to do it like so:
matchID bookingID playerID1 playerID2 playerID3 playerID4
1 1 1 2 3 4

No, "normalization" in this context means you would want to create multiple tables, Match, MatchPlayer, Booking, and Player that relate to one another based on their primary keys. For example:
Match table:
MatchID BookingID
---------------------
PlayerMatch table:
MatchID PlayerID
-------------------
Booking table:
BookingID
----------
Player table:
PlayerID
--------
Now the MatchID is the primary key in the Match table and it's the foreign key in the MatchPlayer table, and the PlayerID is the primary key in the Player table and it's the foreign key in the MatchPlayer table. This creates a "many to many" relationship between matches and players because there can be multiple matches in which a player can participate, and there are obviously multiple players in a given match.
Also, the BookingID is the primary key in the Booking table and it's the foreign key in the Match table, and in this case, there is a "one to many" relationship between bookings and matches because there can be multiple matches at each booking.
This approach allows you, for example, to have one record per player so you can have additional information about a player without repeating that information unnecessarily in the Match table, like first name, last name, age, gender, etc. Similarly, it allows you to have one record that holds information about a booking, like date, venue name, etc.
Given your current example, normalization would seem to be unnecessary since you don't have any additional information about players and bookings, but it seems like your schema could quickly expand to involve more information.

Related

How to create this `check constraint`

I have two tables:
People:
Id | OrgId | Name
-----------------
1 10 Sam
2 10 Dana
3 12 Max
Id is a primary key. OrgId is foreign key to other table.
And second table Cars:
Id | Name | OrgId | PersonId
----------------------------
1 Volvo 10 1
2 BMW 10 2
Here: Id is a primary key. PersonId is a foreign key to People table. OrgId is foreign key to Organization table.
So I have Person which are attached to Organization and I have Cars which are attached to Organization and Person.
I need to guarantee that it will be impossible to attach Car from one Organization to Person from another Organization. The record:
Id | Name | OrgId | PersonId
----------------------------
1 Volvo 12 1
must be impossible because Car belongs to Organization with ID = 12, but Person belongs to Organization with ID = 10.
What is the best way to do it ?
I see two ways:
Foreign key using two fields People (Id + OrgId) <-> Cars (PersonId + OrgId).
But in this case I need to create one additional unique index on the table People ('Id+OrgId`).
Trigger on the table Cars.
What do you recommend to use in this case ?
My first reaction is to look up the organization using the person column. But, that doesn't really fit the situation -- cars are owned by organizations independently of people. So, you might need the organization, even if no person is assigned.
So, add a new key to people:
alter table people add constraint unq_people_orgid_id unique (orgid, id);
Then use this for the foreign key reference in cars:
alter table cars add constraint
foreign key (orgid, personid) references people(orgid, id);
Note that the second key is redundant. But it allows a reference that includes the organization.
I wouldn't use OrgId in your cars table, it violates normalization rules. You can use a query to get the organization information for the car using the PersonId.

Existing table design change in SQL Server

My existing table structure is below:
Students table and columns are below:
Year
Student_Id
Subject_Type_Id
Quarter
Complete_DTTM
Column1
Existing data like below:
Students:
Year Student_Id Quarter Subject_Type_Id Complete_DTTM Column1
---------------------------------------------------------------------------------------
2006 1 1 1 Null x
2006 1 2 1 10/2/2006 xyz
2006 1 2 2 10/30/2006 abc
2006 1 2 3 11/20/2006 def
One student can take multiple subjects by saving each subject separately by picking from DropDownList.
Now new requirement is one student can take multiple subjects by selecting from Checkboxes and provide data for Column1 and Complete_DTTM and save.
The difference between old and new requirement is how user selecting subject types, in old from Drop down list, able to pick one subject only, Column1 and Complete_DTTM are different for each subject.
With the new requirement, they can pick multiple subjects from check boxes for a student and column1 and Complete_DTTM is same for all subjects.
NEW data going to be like below:
Year Student_Id Quarter Subject_Type_Id Complete_DTTM Column1
--------------------------------------------------------------------------
2015 1 1 1, 2, 3, 4 12/31/2015 abcdef
2015 1 2 1, 2, 3, 4, 5 1/1/2016 xyz
How do I change ‘Students’ table (I can add new table) to support multiple subject Ids and also needs to support old data (shown above for year 2006)?
Thanks in advance
You need to make a table that will house just the student data. Then you will need to make a table that will house Subject Type data. The a table to link them together.
CREATE TABLE Student (ID INT NOT NULL PRIMARY KEY, NAME VARCHAR(50) NOT NULL,n...)
Create Table for subject
CREATE TABLE Subject (ID INT NOT NULL PRIMARY KEY, Subject_Name VARCHAR(50)NOT NULL,n...)
Then You will need a table to link these two together.
CREATE TABLE Student_Suject_Link (Student_ID INT NOT NULL, SUBJECT_ID INT NOT NULL)
The link table will need to have a foreign key realtionship to the Student table and the Subject table. Student_ID needs to be a foreign key to the ID column in the student table and same for the subject table. The SUbject_ID needs to be a foreign key to the ID in the Subject table. This should satisfy 3rd normal form. And if you need to grab data it is easy enough to join tables to get what you need. I relaize it seems to create more work but it is infinately easier to manage that adding lists to tables. You can of course add other fields you deem necessary into the table it is just necessary to have the ID's to relate on. Hope this helps.
You now have a one to many relationship and you need a child table for the many part of the relationship. Do not ever store data in a comma delimited list. This is a way to totally break your performance when you want to find data int hose tables. It is just bad deign. You need to normalize those tables and I am sure that this is why you have been given this particular exercise.

Is this a good database design practice?

I got a Person table, each Person can visit several countries. The countries visited by each Person is stored in table CountryVisit
Person:
PersonId,
Name
CountryVisit:
CountryVisitId (primary key)
PersonId (foreign key to 'Person.PersonId')
CountryName
VisitDate
For the CountryVisit Table, my primary key is CountryVisitId which is an identity column. This design will result in that a Person can have only 1 CountryVisit but the CountryVisitId can be 40 for example. Is it a better practice to create another surrogate key column to act as an identity column while the CountryVisitId be a natural key that is unique for each PersonId ?
It is pretty good. I would suggest that you have a separate table for countries, with one row per country. Then the CountryVisits table would have:
CountryVisitId PrimaryKey,
PersonId ForeignKey,
CountryId ForeignKey,
VisitDate
This will ensure that the country name is always spelled correctly and consistently. If you want a list of countries to get started, check out this Wikipedia page. Also note that your definition of country may be different from the standard list of countries (there are actually several out there), so you should use your own auto-incremented primary key, rather than using the country code.
And, you should relax the requirement and remove the unique or primary key on PersonId, CountryId, unless you want to enforce only one visit per country.

Is correct have a table in a 1 to 1 relationship with a FK that is also a PK?

I have one table called Player
PlayerID (PK)
More columns
I want to create another table that has a 1 to 1 relationship to Player named PlayerExtraInfo to contain some columns. So I have several options:
Instead of creating a new table, add PlayerExtraInfo columns to Player table
Create PlayerExtraInfo table and have a FK in Player table.
Player table
PlayerID (PK)
More columns
PlayerExtraInfoID (FK)
PlayerExtraInfo table
PlayerExtraInfo (PK)
More columns
The opposite: PlayerExtraInfo contains a FK to Player table. To get sure that relationship remains 1 to 1 I add a unique constrain.
Player table
PlayerID (PK)
More columns
PlayerExtraInfo table
PlayerExtraInfo (PK)
More columns
PlayerID (FK, Unique)
Similar to option 3 but mixing PK and FK in one. In this case my foreign key becomes also the primary key:
Player table
PlayerID (PK)
More columns
PlayerExtraInfo table
PlayerID (PK, FK)
More columns
I know that options 1, 2 are correct, but due to performance problems I am option for option 3 or 4. And thinking about these 3 and 4 options some doubts about option 4 assault me:
So my questions are:
Are options 3 and 4 correct?
Does option 4 break any normal form?
Is there another option I didn't think about?
When extending one table with another one it is absolutely fine (and recommended as well) to use the primary key as the foreign key.
While options 2,3,4 are correct, I would think that option 1 is the one that will give the best performance. Even when using using clustered indexes, an extra join is an extra join. Also a foreign key will degrade performance in respect to the targeted table (I admit that a large number of foreign keys will degrade it, and not one single).
Except the case where the extended table will have but a fraction of the main table's records, or the case where you would like the 2 tables on different partitions, I cannot think of a reason to have that table split into peaces.

Weak Entity containing a foreign key as a primary key

I have created a table called STUDENT which consists of Unique ID as the PRIMARY KEY along with other related attributes like Name, Addr, Gender etc....
Since I don't want to increase the table size of the STUDENT, I created a weak entity called ACADEMIC RECORDS which stores the previous Academic Records of the student.But in this table i have only created a PRIMARY KEY Unique ID which references the Unique ID of the student. and there is no other attribute in conjunction with Unique ID in the weak entity ACADEMIC RECORD Table.
As I came across the definition OF A WEAK ENTITY which define its primary key as a combination of weak entity's attribute and the owner's table's primary key(in this case STUDENT)
Is my method of creating a foreign key as the only primary key in the table ACADEMIC RECORD correct??
STUDENT Table
**UID** NAME GENDER ADDRESS PHNO.
ACADEMIC RECORD Table
**UID** HighschoolMarks GradSchoolMarks
There's nothing necessarily wrong with having a primary key that's also entirely a foreign key. It's a common way of implementing something like ‘base classes’, where an entity has a row in a base table, and may have a row in one or more extension tables (one to one-or-zero relationship).
I'm not sure it's the most appropriate schema for what you're doing though. If there really is an exactly one-to-one relationship between academic_records and students, it looks like they are part of the same entity to me.
In which case from a normalisation point of view the record columns should be part of the main students table. Maybe there's an efficiency reason to denormalise, but “I don't want to increase the table size” is not normally an adequate reason. Databases can cope with big tables.
I'm not completely clear on what you are asking, but it sounds like you are using the correct method.
Your STUDENT table requires a primary key to provide a unique reference for each row.
Your ACADEMIC_RECORD table also requires a primary key to provide a unique reference for each row.
Each student may have zero or more academic records, and you want to identify the student to which each academic record belongs. You do this by adding a column in the ACADEMIC_RECORD table which contains the id (the primary key) of the student:
STUDENT ACADEMIC_RECORD
id
id <-------> student_id
name high_school_marks
gender grade_school_marks
address
phone_no
Assume you have three students: Alice, Bob and Dave. Alice and Dave have three academic records, and Bob has two. Your tables would look something like this (I've omitted some columns to make things clearer):
STUDENT
id name
1 Alice
2 Bob
3 Dave
ACADEMIC_RECORD
id student_id
1 1
2 1
3 1
4 2
5 2
6 3
7 3
8 3