I have 3 tables:
Product (shamppoo, toothpaste,..)
FrequenceOfUse (3 times/day, once/day,...)
User
As you can imagine I want to store in a database how much the users use products. What should be the relations between those tables?
Javi
It will be a many-to-many relationship between User and Product and one-to-many relationship between FrequenceOfUse and UserProduct (the latter being a relationship itself).
Note that there is no consensus on whether relationships can have relationships on their own. So some would prefer to model it as:
Entity User
Entity Product
Entity Usage
Entity FrequenceOfUse
1-N relationship: User participates in Usage
1-N relationship: Product participates in Usage
N-1 relationship Usage is performed with Frequence
Both these models are relationally modeled as:
CREATE TABLE user (id INT NOT NULL PRIMARY KEY, name TEXT, ...)
CREATE TABLE product (id INT NOT NULL PRIMARY KEY, name TEXT, ...)
CREATE TABLE frequence (id NOT NULL, description TEXT, ...)
CREATE TABLE usage
(
user INT NOT NULL FOREIGN KEY REFERENCES (user),
product INT NOT NULL FOREIGN KEY REFERENCES (product),
frequence INT NOT NULL REFERENCES frequence,
PRIMARY KEY (user, product)
)
You may find this post in my blog useful:
What is entity-relationship model?
Related
I'm trying to accomplish 3NF or third normal form for a small database homework.
I have Students, Classes and Parents.
Here are the tables I need to make:
Student: id, name, grade (avg)
Class: class_id, profile (type of class), class_master, students within said class
Parent: name, address, student enrolled in school
Things that I should point out:
Since my english is not that good, I thought I should specify:
Class is one to many relationship since one student can be part of one class, and only one (thus a class is a collection of students, nothing else).
Profile is a specialization of a class (again, the student grouping mechanism called class). Ex: Profile: Mathematics, Literature, Computer Science
[/Things that I should point out]
Again, I have to make tables that fall within 3NF guidelines, not tables that are exactly like the ones I have just mentioned
I was thinking:
Class:
class_id primary key, foreign key (class_master_name)
Profile:
class_master_name primary key, profile_name
Student:
student_id primary key, name, grade (avg), foreign key (class_id)
Parent:
parent_id primary key, name, address
Thus Class, Profile, Student and Parent would be 3NF since all non key elements refer strictly to the key, the whole key, and nothing but the key.
My problems (or rather specific questions that need answers):
Is the student <-> class relationship OK ? Is it enough that student refers to class ? I could not imagine a way class could have references towards the students without having repeating data that would either conflict with 2NF or 1NF.
Each student has up to two parents (one, or both could be dead or simply unknown). I was thinking of having a table Relationship: student_id, parent_1_id, parent_2_id but I have no idea how to implement this. How could I (in SQL Server Management Studio 2008) make this table (where parent_1_id != parent_2_id and also student_id is the primary key but also a foreign key)
Would this actually be 3NF or am I doing something wrong ?
How I thought of implementing Relationship: student_id, parent_1_id, parent_2_id
CREATE TABLE Relationship (
student_id int NOT NULL PRIMARY KEY,
parent_1_id int,
parent_2_id int,
CONSTRAINT (parent_1_id, parent_2_id) FOREIGN KEY
REFERENCES Parent (parent_id, parent_id),
CONSTRAINT (student_id) FOREIGN KEY
REFERENCES Student (student_id)
)
Is it OK ?
Looks like you need something similar to this:
(Class.ProfileId and Student.ClassId are NOT NULL, while Parent1Id and Parent2Id are NULL-able.)
ClassType:
classtype (primary key)
name
etc...
Class:
classid (primary key)
classtype (foreign key)
classname
etc...
Person:
personid (primary key)
name
dob
etc....
ClassStudent:
studentid (primary key)
classid (foreign key)
personid (foreign key)
grade
etc
PersonRelation:
relationid (primary key)
prim_personid (foreign key)
sec_personid (foreign key)
relationship (parent, sibling, etc)
etc
I have to create a database having only 2 tables student and course. There is no relation between them or say atmost 1 relation is acceptable.
Query that usually runs on it :-
"Get courses registered by a student".
So it should be quick to respond. Please tell how to implement such database?
CREATE TABLE STUDENT
(student_id INT PRIMARY KEY)
CREATE TABLE COURSE
(course_id INT PRIMARY KEY)
CREATE TABLE COURSE_REGISTRATIONS
(
student_id INT,
course_id INT,
)
In COURSE_REGISTRATIONS, the {student_id, course_id} combination is the primary key, and obviously student_id and course_id are foreign keys to their respective table.
You can query COURSE_REGISTRATIONS for the information you need.
Say I have a database with multiple entitles like person, company, conference for which you have to keep track of say addresses. We can have multiple addresses for the same entity (person). One approach is to have a separate address table for each entity (person_address etc). Another approach is to have an address table which has primary key (Entity,id,address_type). In this approach we cannot use foreign keys from address table to entities .
So what is the better approach. Is there another way to do this ?
thanks
At a logical modeling POV your descriptions highlights the fact that the entities like person, company, conference etc have a common trait: they have zero, one or more addresses. If you would model this as a class hierarchy, perhaps you would create an Addressable class and have person, company and conference inherit from this Addressable class. You can apply the same reasoning to your data model and have an addresable table with an addressable_entity_id. The person, company, conference entities would 'inherit' this table. There are three established ways to implement table inheritance:
Class Table Inheritance
Single Table Inheritance
Concrete Table Inheritance
So you could model your tables like this:
create table Addresses (AddressId int not null identity(1,1) primary key, ...);
create table Addressable (AddressableId int not null identity (1,1) primary key, ...);
create table AddressableAddress (
AddressId int not null,
AddressableId int not null,
constraint AddressableAddressAddressId
foreign key (AddressId) references Addresses(AddressId),
constraint AddressableAddressAddressableId
foreign key (AddressableId) references Addressable(AddressableId));
create table Person (PersonId int not null identity(1,1) primary key,
AddressableId int not null,
...,
constraint PersonAddressableAddressableId
foreign key AddressableId references Addressable (AddressableId));
create table Company (CompanyId int not null identity(1,1) primary key,
AddressableId int not null,
...,
constraint CompanyAddressableAddressableId
foreign key AddressableId references Addressable (AddressableId));
Of course you have to find the right balance between absolute relational normal form and actual usability. In this scheme I propose for instance in order to insert a new Person one has to first a row in Addressable, get the AddressableId and then proceed and insert the person. This may or may nor work. BTW, there is a way to do such an insert in one single statement using the OUTPUT clause to chain two inserts:
insert into Addressable (AddressableType)
output inserted.AddressableId, #FirstName, #LastName
into Person (AddressableId, FirstName, LastName)
values (AddressableTypePerson);
But now is difficult to retrieve the newly inserted PersonId.
Technically if two people live at the same address you would not be completely normalized if there was simply a single one-to-many detail table for the row in TBLPerson called TBLAddress However, if you want just one instance per physical address you will incur the overhead of a many-to-many relation table of TBLPersonAddresses which FK's to TBLAddress
I would say that unless you expect multiple people at the same address to be the norm that I would simply have the TBLAddress with column personID as a detail to the TBLPerson
EDIT: And I tend to always use surrogate keys unless I have a specific reason not to do so.
If I use the primary key of a table as the primary key of another table is it still a foreign key?
e.g.
Two tables albums and special offers
AlbumId is the primary key in both
How do I represent this relation using primary key foreign key notation?
Yes, it's still a primary key. It's usually called a one-to-one relation.
You can do something like:
create table albums (
album_id integer primary key,
-- other fields...
);
create table special_offers (
album_id integer primary key references albums(album_id),
-- other fields...
);
if e.g you have several special offers for the same album AlbumId is no longer unique in the special offers table. I would think about adding a SpecialOfferId and design a one-to-many relation.
Pablo Santa Cruz is right - yes, you're allowed to do this. However, philosophically, it's only meaningful if there really is a one-to-one relationship - all albums have one and only one special offer, and all special offers have one and only one album.
Guessing from your problem domain, that's not the case - some albums have no special offers, some have 1, some have many.
If that is indeed true, bw_üezi is right - create a one-to-many relationship.
create table albums (
album_id integer primary key,
-- other fields...
);
create table special_offers (
special_offer_id integer primary key,
album_id integer foreign key references albums(album_id),
-- other fields...
);
My teach said I should combine two foreign keys into a single primary key. But my thought process is that that would allow for only one combination of each foreign key.
Imagine I have a Product, Purchase, PurchaseDetail.
In PurchaseDetail I have two foreign keys, one for product and one for purchase. My teacher said that I should combine these two foreign keys into a single one. But can't a product be in many different purchases? And many purchases have many products?
I'm confused.
Thanks!
Edit: This is the SQL my teacher saw and then gave feedback upon. Thanks for the guidance guys. (I changed the essential to English)
create table Purchase
(
ID int primary key identity(1,1),
IDCliente int foreign key references Cliente(ID),
IDEmpleado int foreign key references Empleado(ID),
Fecha datetime not null,
Hora datetime not null,
Amount float not null,
)
create table PurchaseDetail
(
ID int primary key identity(1,1),
IDPurchase int foreign key references Purchase(ID),
IDProductOffering int foreign key references ProductOffering(ID),
Quantity int not null
)
create table Product
(
ID int primary key identity(1,1),
IDProveedor int foreign key references Proveedor(ID),
Nombre nvarchar(256) not null,
IDSubcategoria int foreign key references Subcategoria(ID),
IDMarca int foreign key references Marca(ID),
Fotografia nvarchar(1024) not null
)
create table ProductOffering
(
ID int primary key identity(1,1),
IDProduct int foreign key references Product(ID),
Price float not null,
OfferDate datetime not null,
)
Maybe I'm confused about good database schema design. Thanks again!
I imagine he's suggesting:
Product - one primary key (product id), which implies a unique product id
Purchase - one primary key (purchase id), which implies a unique purchase id
PurchaseDetail - two foreign keys (product id),(purchase id), plus one unique constraint on (product id + purchase id)
Plus some people argue that all tables should have their own primary key that doesn't depend on anything else (purchase detail id). Some DBMS make this mandatory.
This means that you can't have two rows in PurchaseDetail that have the same product and purchase. That makes sense, assuming there is also a quantity column on PurchaseDetail, so that one purchase can have more than one of each product.
Note that there is a difference between a unique constraint and a foreign key. A foreign key merely says that there should be an item with that id in the parent table - it will let you create as many references to that item as you want in the child table. You need to specify that the column or combination of columns are unique if you want to avoid duplicates. A primary key on the other hand implies a unique constraint.
Exact syntax for defining all of this varies by language, but those are the principles.
I don't agree with the single key, but they could be a compound key (which I tend to dislike). They can be two different fields each restricted to the ID in the corresponding tables.
Not sure why the same product iD would need to be listed more than once for a single purchase? Isn't that why you indicate quantity? Maybe the need to do a separate line item for a purchase and a discount?
I believe thelem has answered correctly. But there is another option. You could add a new primary key column to the details table, so it looks like this:
detail_id int (PK)
product_id int (FK)
purchsae_id int (FK)
This is not really necessary, but it could be useful if you need to ever need to reference the details table as a foreign key - having a single primary key field makes for smaller indexes and foreign key reference (and they are a little easier to type).
That depends on what data you need to represent.
If you use the two foreign keys as the primary key for the purchase detail, a product may only occur once in each purchase. A purchase may however still contain many products, and a product may still occur in many purchases.
If the purchase detail contains more information, you may need to be able to use a product more than once in a purchase. For example if the purchase detail contains size and color, and you want to by a red T-shirt size XL and a blue T-shirt size S.
Perhaps he is suggesting a many-to-many table where it's Primary Key is comprised of the Foreign Keys to the mapped tables:
PurchaseDetail:
ProductId int (FK)
PurchaseId int (FK)
PK(ProductId, PurchaseId)
This can also be modelled as
PurchaseDetail:
PurchaseDetailId int (PK, Identity)
ProductId int (FK)
PurchaseId int (FK)
The second form is useful if you want to refer to Purchase details elsewhere in your model, and also in some RDBMS's it is beneficial to have a PK on a montonically increasing integer.