Database normalisation - some issues - sql

I am completing some work for Uni and have a single table of data that i need to arrange into 1st,2nd and 3rd Normal Form, i have attempted to do so below but i have hit a brick wall with it.
I would appreciate any helpful input at all as my tutor is away on holiday and I don't want to start the rest of the work using the wrong tables/relations to start with.
Basically the system is supposed to allow users to add films, directors and actors. Allow multiple users to review films and categorise the films by genre.
UNF
**filmID**
title
directorID
categoryID
categoryName
notes
directorName
actorName
actorID
role
userID
userName
reviewDate
reviewText
1NF
**filmID**
title
notes
**directorID**
directorName
**categoryID**
categoryName
**actorID
filmID***
actorName
role
**userID**
userName
**filmID*
userID***
reviewDate
reviewText
2NF
**filmID**
title
notes
**directorID**
directorName
**categoryID**
categoryName
**actorID**
actorName
**actorID
filmID***
role
**userID**
userName
**filmID*
userID***
reviewDate
reviewText

You'll find here on Stack Overflow that people won't answer your homework for you.
However here's a link to a very good tutorial.
Normalisation Tutorial
You'll understand it much better if you work through it and complete it yourself, rather than copying and pasting the answer from here.

Here are some questions for you...
Can an actor also be a director?
Can a film have more than one director?
Can a user review a film more than once?
Are the genres predefined?
Can an actor play more than one role in a film?

It's entirely possible that a database that meets the criteria for 2nd Normal Form also meets the criteria for 3rd Normal Form. It looks like that is the case here.

Related

SQL aspx homework, stuck on doing a search advice?

Hey all first post here. I'm utterly lost on our assignment in my web database integration with c# course. My DB is a simple gradebook outlined below. The assignment is to search on an aspx page, and go to a search result page that show's in gridview the results of the DB query. We need to search for classes by department name and also a separate search page for searching by class name.
I know I have to join the tables somehow with sql, but can't recall how. I've been out sick playing catch up now that I'm back. Below is my DB outline, PK is primary KEY.
Department
DepartmentID PK - linked to Table Class 1tomany
DepartmentName
Class
ClassID PK
ClassName
DepartmentID
CreditHours
I am lost when it comes to which page gets what datasources as well, the input search page with the txtbox for the search, or the search results page that has the results? Using Visual Studio and Microsoft Access as required by the course, thank you all!
EDIT Cindy was kind enough to help me on the inner join sql I was looking for, now if I can figure out the datasources I'm golden from there. Thanks Cindy!
You actually have several questions. I can answer one of them. But honestly, you'd be better off asking your teacher or a classmate for help.
To see all the classes and their department names,
SELECT ClassID, ClassName, CreditHours, class.DepartmentID, DepartmentName
FROM Class
INNER JOIN Department ON Department.DepartmentID = Class.DepartmentID
What this does is collect all the classes and connect them to their departments, matching ON the departmentID field that's stored as part of the class row. Here's a good explanation. https://support.office.com/en-in/article/Join-tables-and-queries-3f5838bd-24a0-4832-9bc1-07061a1478f6

Using LIKE in SQL Server to identify strings

I am writing a program that performs operations on a database of Football matches and data. One of the issues that I have is that my source data does not have consistent naming of each Team. So Leyton Orient could appear as L Orient. Most of the time this team is listed as L Orient. So I need to find the closest match to a team name when it does not appear in the database team name list exactly as it appears in the data that I am importing. Currently in my database I have a table 'Team' with a data sample as follows:
TeamID TeamName TeamLocation
1 Arsenal England
2 Aston Villa England
3 L Orient England
If the name 'Leyton Orient' appears in the data being imported I need to match this to L Orient and get the TeamID 3. My question is, can I use the LIKE function to achieve this in a case where the team name is longer than the name in the database?
I have figured out that if I had 'Leyton Orient' in the table and was importing 'L Orient' I could locate the correct entry with:
SELECT TeamName FROM Team WHERE TeamName LIKE '%l%orient%';
But can I do it the other way around? Also, I could have an example like Manchester United and I want to import Man Utd. I could find this by putting a % sign between every character like this:
SELECT TeamName FROM Team WHERE TeamName LIKE '%M%a%n%U%t%d%';
But is there a better way?
Finally, and this might be better put in another question, I would like not to have to search for the correct team when the way a team is named is repeated, i.e. I would like to store alternative spellings/aliases for teams in order to find the correct team entry quickly. Can anybody advise on how I might approach this? Thanks
The solution you are looking for is the FULL TEXT SEARCH, it'll require your DBA to create a full text index, however, once there you can perform much more powerful searches than just character pattern matching.
As the others have suggested, you could also just have an Alias table, which contains all possible forms of a team name and reference that. depending on how your search is working, that may well be the path of least resistance.
Finally, and this might be better put in another question, I would like not to have to search for the correct team when the way a team is named is repeated, i.e. I would like to store alternative spellings/aliases for teams in order to find the correct team entry quickly. Can anybody advise on how I might approach this? Thank
I would personally have a team table and a teamalias table. Use relationships to marry them up.
I believe the best way to prevent this, is to have a list of teams names displayed in a dropdown list. This will also let you drop validation for the team name. The users can now only choose one set team name and will also make it much easier for you working in your database. then you can look for the exact team name as it appears in your database. i.e.:
SELECT TeamName FROM Team WHERE TeamName = [dropdownlist_name];

Database design for an online quiz

I am designing an online math quiz for a college project and having some trouble with designing my database.
The basic idea of the website is as follows:
A teacher, once registered may log in and add questions to their account. They can choose between making the questions multiple choice OR true or false. They can also choose between making their questions public or private. (If they choose to make the questions public, other teachers may view the questions.)
At any time the teacher may create a quiz for their students using the questions in their private bank and / or questions from the public bank. Each question may be used in multiple quizzes.
The idea is that the students will later log in and do the quiz; their answers are stored and the teacher can generate reports and check how the students did individually / highest and lowest scoring questions etc.
I am having some trouble deciding how to store the quizzes and questions which I hope somebody may be able to help me with.
So far I have the following:
‘Question’ table with attributes: QuestionID, SubjectArea, Concept, QuestionText, TeacherID, QuestionType, PublicYorN
‘MCQuestions’ table with attributes: QuestionID, AnsA, AnsB, AnsC, AnsD, AnsE, CorrectAns
‘TorFQuestions’ table with attributes: QuestionID, CorrectAns
‘Quiz’ table with attributes: QuizID, CreationDate, TeacherID
I think I then need another table as follows:
‘QuizQuestions’ and the only attributes will be QuizID, QuestionID which together make a concatenated primary key.
I feel like I should have a separate table to store answers to questions and I'm not sure if I need to separate true or false questions and multiple choice questions as I have done above.
(Obviously there are other tables containing user data etc. but this is the part I’m concerned with.)
Any advice / input is greatly appreciated!
A simple yet flexible design would be something like this:
Questions table (id, text, correct answer id, all the other question related data)
Answers table (id, question id text, all the other answer related data)
Quiz table (id, text, all the other quiz related data)
Quiz questions table (quiz id, question id, question display order, other related data such as question weight might also be added)
Quiz results table (quiz id, question id, answer id, user id, all the other related data such as date of answer and such).
I think my only input to this open ended question is:
Combine MCQuestions and TorF Questions to have a different format. Answers table has 4 cols. QID, AnswerID,answer,Correct Y/N.
Then a true or false question has 2 rows - eg. QID=888, AID=1,Ans=TRUE,true. Next row is QID=888, AID=2,Ans=FALSE,false.
Multiple choice has several - so which is the bright yellowy thing? QID=889, AID=3,Ans=Moon,false. QID=889, AID=4,Ans=Sun,true. QID=889, AID=5,Ans=Mars,false.
Then you grab a list of answers and can populate a set of radio buttons with the QID and AID values. Then you are matching integers in your code rather than long text strings which will need to be passed around for matching. Might make it a bit easier in case of special chars in the answers or whatever and you're matching the quiz results to a unique key.
Apart from that minor change it's difficult to help without knowing any other constraints...
Nick

What sort of database design would I need to use in case I wanted users to save tags, and be able to call already used tags?

I'm trying to implement a feature similar to StackOverflow's tag feature. That a user can create a new tag, or by typing pull up a list of similar tags already created.
This is such a wonderful feature on this site and I find it sad that most sites do not have something like this. It's both robust, and yet very very flexible and best of all: driven by the community.
So I have these two tables:
Company
id
email
name
companySize
countryOfOrigin
industryid
Industry
id
description
Every time a user writes a new tag, I want to create one with a unique ID, and also be able to search for existing tags.
Will this database design allow for an easy and efficient implementation of this feature?
If not, please give a little guidance. :)
Whilst there's not a tremendous amount of information to go on, what you've listed should be fine. (The 'tag' being the 'description' field in the industry table, etc.)
As you might imagine, all of the real work is done outside of SQL, where you'll need to...
(Potentially) add new tag(s) that don't yet exist.
Associate the industry with the supplied tag(s).
(Potentially) prune previously used tags that may no longer be in use.
...every time you edit an industry.
That said, the key limitation of your proposed setup is that each company can only belong to a single industry. (i.e.: It can only have a single industry tag associated with it.)
As such, you might want to consider a schema along the lines of...
Company
id
...
countryOfOrigin
Industries
id
description
CompanyIndustriesLookup
companyID
industryID
...which would let you associate multiple industries/tags with a given company.
Update...
For example, under this setup, to get all of the tags associated with company ID 1, you'd use...
SELECT Industries.description FROM (CompanyIndustriesLookup, Industries)
WHERE companyID=1 AND industryID=Industries.ID
ORDER BY Industries.description ASC;
On a similar basis, to get all companies tagged with an industry of "testing", you'd use...
SELECT Company.name FROM (Company, Industries, CompanyIndustriesLookup)
WHERE Company.id=CompanyIndustriesLookup.companyID
AND Industries.id=CompanyIndustriesLookup.industryID
AND Industries.description="testing"
ORDER BY Company.name ASC
A very easy (if somewhat suboptimal, but it often does not matter) solution to use tags is to not have tag ids at all. So, you have:
Items
ItemId
Name
Description
...
ItemTag
ItemId
Tag
Adding a tag to an item is just adding the tuple to the ItemTag table, whether the tag already exists or not. And you don't have to do any bookkeeping on removing tags either. Just keep an index on ItemTag.Tag, to be able to quickly display all unique tags.

Custom sort-order with SQL-Server and .NET Entity-Framework

I have a table I store contacts and their phones.
Contact: ContactId (int, PK), FirstName (varchar), LastName (varchar)
Phone: PhoneId (int, PK), ContactId(int FK), Number (varchar), SortOrder (tinyint)
I want that under each contact, the user should be able to maintain the priority of the phones, meaning that the SortOrder column of phone should be under each ContactId by consecutive numbers.
For exmple, when adding the first phone to a user, its SortOrder should become 1, for the second 2 and so on.
Say the user added 5 phone to a user, now he wants to move phone (with order) 3 to place 2, it should push current 2 to place 3 and vice versa.
If he want to make phone 1 to last it should 'pull' all the phones' SortOrder by -1, then assign previous 1 to 5.
I want this system to be consistent and not to have open edges where I have:
2 phones with identical sort-order values in one group
First phone in group with value higher than 1
Last phone in group with value higher or smaller than amount of phones in group
etc. etc. etc.
I think I am pretty clear so far (am I).
Now my question is, considering I retrieve the data with .NET EF in a desktop app, and I will be accessing the phones using the Contact.Phones navigation property.
Should implement this system in the DAL or in server AFTER INSERT, UPDATE trigger?
I personally think this has to be implemented on the server, cuz imagine different users play around with the same contact-phones at the same time, this might break the consistency, huh?
Any tips, links, code, advice jokes regarding this custom-sorting issue will be welcommed.
I also thought about ROWNUMBER() as a good idea of retrieving the data, but I need to maintain the sorting, not only selecting it.
Notes:
In general I asked the question in continuation of this answer, I decided to use, the contact-phone example was just to make things simple.
I've found this post discussing my issue but no technical advise was provided there.
Thanks in advance.
Your square pegging a round hole here.
Your answer CAN be as easy as Contact.Phones.OrderBy ( #p => #p.SortOrder ) then taking care of all of your phones in a Contact.SetPhone( phone, order ) method which can encompass whatever custom logic you wish.
Also since this is business and view logic your persistence store shouldn't be aware of whats going on.