Student(ID, name, address, GPA, sizeHS) // ID is key Campus(location, enrollment, rank) // location is key Apply(ID, location, date, major, decision) // (ID,location) is key
Campus" returns all tuples in Campus relation.
Relational algebra operators used to combine, filter, etc. the relations:
SELECT operator (Example: Students with GPA > 3.7 and sizeHS < 1000)
(Example: Applications to S.C. geology major)
** General case:
SELECT_{C} R
where C can use attribute names, constants,
comparisons (=, <, etc.), and connectives
(AND,OR,NOT)
PROJECT operator PROJECT eliminates columns while SELECT eliminates rows.
To do both, combine ("compose") operators:
(Example: name and address of Students with GPA > 3.7 and sizeHS < 1000)
SELECT produces a relation, PROJECT operates on that relation.
** General case: PROJECT_{A1, A2, ..., Am} E
where E is any expression producing a relation
Question: Is it ever useful to compose two projection operators?
Example: PROJECT_{enrollment} PROJECT_{location, enrollment} Campus
Question: Is it ever useful to compose two selection operators?
Example: SELECT_{sizeHS < 1000} SELECT_{GPA > 3.7} Student
PROJECT_{date,decision} Apply can produce many
tuples with same value
Campus X Apply
Schema of result is schema(Campus) union schema(Apply)
Formally: R1 X R2 = {t | t = <t1,t2> and t1 in R1 and t2 in R2}
Question: Looks odd to glue unrelated tuples together. Why use it?
(Example: Names and addresses of all students with GPA > 3.7 who applied to CS major and were rejected)
Question: Can we write it in a different way?
(Show schema of Campus JOIN Apply)
(Example: Names and addresses of all students with GPA > 3.7 who applied to CS major and were rejected)
(Example: Names and addresses of all students with GPA > 3.7 who applied to CS major at campus with enrollment < 15,000 and were rejected)
** General case:
E1 JOIN E2 = PROJECT_{schema(E1) U schema(E2)} SELECT_{E1.A = E2.A and E1.B = E2.B and ...} (E1 X E2)
Need to be careful -- suppose we have:
Student(ID, name, address, GPA, sizeHS) Campus(name, enrollment, rank)"
Student JOIN Campus" doesn't make sense.
E1 JOIN_{C} E2 = SELECT_{C} (E1 X E2)
Student(ID, name, address, GPA, sizeHS) OutofStateStudent(ID, name, address, GPA, sizeHS, state) ForeignStudent(ID, name, address, GPA, country)
(Example: List name and address of all students)
Question: Can we do it with cross-products or joins?
For union operator:
Student(ID, name, address, GPA, sizeHS) // ID is key Campus(location, enrollment, rank) // location is key Apply(ID, location, date, major, decision) // (ID,location) is key(Example: Find ID's of all students who didn't apply anywhere)
Question: What if want name of students?
For difference operator:
E1 INTERSECT E2 = E1 - (E1 - E2)
Student(ID, name, address) Parent(child-ID, parent-name)(Example: Print list of all student and parent names)
(Example: Find names of all pairs of students who live at same address)
** General case:
RENAME_R(A1, A2, ..., Am) E
RENAME_R E and RENAME_{A1, A2, ..., Am} E
E ::= R
| SELECT_{C} E
| PROJECT_{A1, A2, ..., An} E
| E1 X E2
| E1 U E2
| E1 - E2
| RENAME_{R(A1, A2, ..., Am)} E
| (E)
Abbreviations:
| E1 JOIN E2
| E1 JOIN_{C} E2
| E1 INTERSECT E2
| TempName(A1, A2, ..., Ak) := E
| E1 ; E2