Solutions for CS145 Final

Problem #1: Relational algebra expressions over R(a,b) and S(b,c)
Correct: c) The answer to Q2 is always contained in the answer to Q1.

Note that both Q1 and Q2 result in a subset of R.

A tuple  R(a,b) is selected  by Q1 if  there exists *some* tuple  in S
such that S.b = R.b. This is equivalent to the following SQL query:

  Q1:   SELECT * FROM R WHERE   R.b = ANY (SELECT S.b FROM S)

   
A tuple R(a,b) is produced as output by Q2 if (there exists some tuple
S(b,c) with S.c  = R.a) and (there exists some  tuple S(b,c) such that
S.b = R.b). This is equivalent to the following SQL query:

  Q2:   SELECT * FROM R WHERE ((R.b = ANY (SELECT S.b FROM S)
                           AND (R.a = ANY (SELECT S.c FROM S))

The two SQL queries make it clear that Q2 produces a subset of tuples
produced by Q1.

Problem #2: SELECT ALL or ANY with subquery
Correct: d) Q1 and Q2 produce different answers.

There are two cases to consider:

- Subquery returns empty set

  ALL (empty set) returns TRUE while ANY (empty set) returns FALSE.
  So Q1 produces all of R.a while Q2 returns empty bag.

- Subquery returns non-empty set

  Usually, the condition b >= ALL (some_non_empty_set) will select
  fewer tuples than the condition b >= ANY (some_non_empty_set).

Problem #3: SELECT w/ GROUP BY   vs   SELECT DISTINCT
Correct: a) Q1 and Q2 produce the same answer.

Q1 returns the _set_ (not a _bag_) of "a" values whose
corresponding "b" value is positive.

Q2 first groups  selects tuples with positive "b"  values, groups them
by "a"  values and then selects  the "a" values of  these groups. Note
that the GROUP BY  produces a _set_ of groups whose key  is the set of
attributes over which we created groups.

Problem #4 Team/Player ODL Problem #1
Correct: a) Q1 and Q2 produce the same answer.

Both  of them  print names  of  players who  play for  team with  name
"49ers".  Note that there is a unique team with that name because Team
has key "name".

Problem #5: Team/Player ODL Problem #2
Correct: d) Q1 and Q2 produce different answers.

The Types  of the  answer set  of the two  queries are  different.  Q1
produces output of type Bag(Struct(string)) whereas Q2 produces output
of type Bag(Struct(Set(class Player))).

Problem #6: Datalog Cousin/Sibling/GrandParent
Correct: d) Q1 and Q2 produce different answers.

We can rewrite Q1 by substituting Sibling into the second rule:

  Cousin(x,y) <- Par(x,xp) AND Par(y,yp) AND Par(xp,g) AND Par(yp,g) AND xp <> yp

We can rewrite Q2 by substituting GrandParent into the second rule:

  Cousin(x,y) <- Par(x,xp) AND Par(xp,g) AND Par(y,yp) AND Par(yp,g) AND x <> y

The two expressions are identical except for the last condition.

Here is how the last inequality affects the answers:

Consider Par() relation with the following tuples:

   { (x, a), (x, b), (a, g), (b, g),        (u, c), (v, c), (c, h) }

Then,
        Q1 produces Cousin(x, x)
        Q2 produces Cousin(u, v)

Problem #7 Arc(x,y) Problem
Correct: a) Q1 and Q2 produce the same answer.

V(x, degree) is a _set_  of tuples where the second attribute "degree"
is  the  out-degree of  node  "x" in  the  multi-graph  (a graph  with
"parallel"/"multiple" edges).

Let neighbour(x) denote  the _bag_ of neighbours of  x (i.e., there is
one occurence of y in neighbour(x) for each occurence of Arc(x,y)).

Q1 computes the sum of out-degrees of nodes in the _bag_ neighbour(0).

Q2 computes the  cross product of a1 with a2  and selects those tuples
where (a1.x =  0 AND a1.y = a2.x). Finally, the  count of these tuples
is    produced.   Effectively,    Q2   iterates    over    the   _bag_
neighbour(0). Each node y in neighbour(0) contributes out-degree(y) to
the final sum.

Problem #8: COUNT vs COUNT DISTINCT
Correct: d) Q1 and Q2 produce different answers.

If R is the bag <(a,b,c), (a,b,c)>, Q1 produces 1 whereas Q2 produces 2.

Problem #9: UPDATE with INSERT/SELECT
Correct: d) Q1 and Q2 produce different answers.

This question is slightly tricky.

(a) If R has  no tuple with a = 20, then Q1  produces an empty bag but
    Q2 produces a single tuple (10, 20).
    
(b) If R has  several tuples with a = 20, then  Q1 produces a bag with
    as many  occurences of (10, 20) as  there were tuples with  a = 20
    earlier (Note that  a is not the key for R.  So there could easily
    be  duplicates).  However, Q2  produces only  a single  tuple (10,
    20).

Problem #10: SELECT with "a IS NULL" vs "a NOT LIKE '%'"
Correct: c) The answer to Q2 is always contained in the answer to Q1

 The '%'  regular expression matches  all NOT NULL  strings (including
 the empty string with length zero).  It is like "*" when using "ls *"
 in UNIX.

 Q2 always produces an empty bag because
    - "a NOT LIKE '%'" does not match any NOT NULL string R.a.
    - If R.a IS NULL, the outcome is UNKNOWN and the corresponding row
      doesnt get selected.

 Q1 produces all those rows where R.a IS NULL.

Problem #11: R(a, b) and S(b, c)
Correct: c) The answer to Q2 is always contained in the answer to Q1.

Q1 natural-joins R  and S and then selects the  first column. The size
of the answer is equal to the size of (R NATURAL JOIN S).

Q2 selects those tuples in R whose b attribute exists among the bag of
b attributes of S. The size of the answer is never more than the size
of R itself.

Example: R = {(1,2)} and S  = {(2,3), (2,4), (2,5)}.  Then, Q1 = <(1),
(1), (1)> whereas Q2 = <(1)>.

Problem #12: R(x, y, value) problem
Correct: b) The answer to Q1 is always contained in the answer to Q2.

Q1 is equivalent to:

  SELECT S.value
   FROM
     ((SELECT * FROM R)
      MINUS
     (SELECT R1.x, R1.y, R1.value FROM R R1, R R2
             WHERE (R1.x = R2.x OR R1.y = R2.y) AND (R1.value < R2.value)))
      S ;

Q2 is equivalent to:

  (SELECT MAX(R.value) FROM R GROUP BY R.x)
   UNION
  (SELECT MAX(R.value) FROM R GROUP BY R.y) ;

Consider R  = {(0,0,0), (0,2,200), (5,2,500)}. Then,  Q1 = {(500)}
whereas Q2 = {(0), (200), (500)}. Try them in Oracle.

Problem #13: Relational algebra expressions
Correct: c) The answer to Q2 is always contained in the answer to Q1.

Q1 is the cross product of all values in R.a with all values in R.b.

It is easy to see that Q2  cannot possibly produce a tuple that is not
contained in Q1.

What remains  to be determined is  whether there is some  tuple in the
cross  product  that  Q2   cannot  produce.   There  indeed  are  such
tuples.  For example,  if  R =  {(5,5)},  Q1 =  {(5,5)}  whereas Q2  =
{}.   Another   example  is   R   =   {(1,2),   (2,3)}  where   Q1   =
{(1,2),(1,3),(2,2),(2,3)} whereas Q2 = {(1,2), (2,3), (2,2)}

Problem #14: XPath problem
Correct: d) Q1 and Q2 produce different answers.

Q1 allows tag patterns like <A><B></B><B></B><C></C></A> that Q2 does not.

Q2 allows <A><B></B><A><C></C></A></A> that Q1 does not.

Problem #15: Two SQL queries
Correct: b) The answer to Q1 is always contained in the answer to Q2.

In Q1,  there is one tuple per  unique value of attribute  R.a (due to
the  GROUP BY).   Each of  these tuples  is produced  by  Q2. However,
neither a nor  b nor (a,b) is  a key for R. Therefore,  there could be
multiple rows that  share a and b attributes.   Thus, Q2 might produce
the same row more than once.  One such relation where this would occur
is R = {(1, 2, 3), (1, 2, 4)}.

Problem #16: E/R Diagram
Correct: a) I only

R has two FD's: ABC -> D and ABD -> C.

  I  ABC -> D is violated.

 II  Neither FD is violated. The tuples do not share ABC or ABD
     attributes.

III  Neither FD is violated. The tuples do not share ABC or ABD
     attributes.

Problem #17: Keys of Projected Relation
Correct: c) Only AB and AC are keys

There are four FD's: A -> D, B -> C,  D -> E and CE -> B.  A is not on
the  right hand side  of any  FD. So  A must  be part  of any  key for
R. This leaves us with four possible  keys: A, AB, AC, and ABC.  It is easy
to see that:

    A -> ADE
   AB -> ABCDE
   AC -> ABCDE
  ABC -> ABCDE

Thus, the keys for R are AB and AC.
ABC is not a key because it properly contains a key.

It is important  to note that when considering  the projected relation
R, we  do not "project  out" FD's.  All  of  them  need  be considered
when reasoning about FD's in R.

Problem #18 MVD's
Correct: c) I and II only

We know that A ->-> BC and D -> B.

Claim: A ->-> BC and D -> B imply that A -> B.
Proof:
  Consider two tuples that share the  A attribute: (a, b1, c1, d1, e1)
  and (a, b2, c2, d2, e2).  From A ->-> BC, we deduce that (a, b2, c2,
  d1, e1) must also belong to R.  Now, consider the tuples (a, b1, c1,
  d1, e1) and (a, b2, c2, d1, e1) along with the FD D -> B. It follows
  that b1 = b2. This implies that A -> B holds.

  
Claim: A ->-> BC and A -> B imply that  A ->-> C
Proof:
  Consider two tuples satisfying  A -> B:
      (a, b, c1, d1, e1) and (a, b, c2, d2, e2)
  From A ->-> BC, we deduce that (a, b, c2, d1, e1) and (a, b, c1, d2,
  e2) must also belong to R. This implies that  A ->-> C holds.

We cannot assert that A ->-> D holds.
In particular, a relation consisting of the two tuples (a, b, c, d1, e1)
and (a, b, c, d2, e2) satisfies the given dependencies, but not A ->->
D.


Problem #19 E/R Diagram and ODL
Correct: b)  class A {relationship B R inverse B::R} ;
             class B {relationship set<A> R inverse A::R ;
                      relationship C S inverse C::S} ;
             class C {relationship set<B> S inverse B::S} ;

This schema declares class A with A::R being a many-one relationship from A
to B. Class B has a one-many relationship from B to A (a single value
of B can be related to a set of values in A).

The relationships B::S and C::S are defined analogously.

Problem #20 /\, \/ and - with bag interpretations
Correct: b) R \/ (S /\ T) = (R \/ S) /\ (R \/ T)

The four options were:

 (a) R \/ (S - T)  = (R \/ S) - T
 (b) R \/ (S /\ T) = (R \/ S) /\ (R \/ T)
 (c) R /\ (S \/ T) = (R /\ S) \/ (S /\ T)
 (d) None of the above
 
Consider  a tuple  x that  occurs  r, s  and t  times  in R,  S and  T
respectively. The question is equivalent to identifying as to which of
the following identities is really true:

 (a) r + max(s-t, 0) = max ((r + s) - t, 0)
 (b) r + min(s, t)   = min (r+s, r+t)
 (c) min(r, s+t)     = min(r, s) + min(r, t)
 (d) None of the above

Note that terms  like R \/ S, R /\  S and R - S  have been replaced by
r+s, min(r,  s) and max(r-s,  0) respectively because  they faithfully
capture bag semantics.

Only option  (b) is correct for  integers, in general.

Problem #21: FD's and Lossless Joins
Correct: b) AD, BDE, and ABC

A join of two relations is lossless whenever the intersection of their
attributes  functionally  determines   one  of  the  relations.   This
condition  applies  whenever we  decompose  in the  BCNF-decomposition
algorithm, incidentally.   In decomposition (b),  we can join  AD with
ABC  first, since  the intersection,  A, functionally  determines ABC.
That  gives  us  ABCD,  which  must  be joined  with  BDE.   Now,  the
intersection is BD,  and a given FD  tells us BD -> BDE,  so this join
too is lossless.

To  check that  none of  the  other choices  has a  lossless join,  we
construct  counterexamples.   In each  case,  let's  start with  three
hypothetical   tuples  that   when  projected   and  joined   give  us
(a,b,c,d,e).  For instance, in choice (a), these tuples would have the
form  (a,b,c1,d1,e1), (a2,b,c,d2,e2),  and  (a3,b,c3,d,e).  Apply  the
given  dependencies  to equate  certain  symbols,  if necessary.   For
answer (a), we would have to admit that c1 and c3 are both c, but then
we  have three  tuples  that satisfy  the  given FD's:  (a,b,c,d1,e1),
(a2,b,c,d2,e2),   and   (a3,b,c,d,e).   Since   none   of  these   are
(a,b,c,d,e),  we know  that  the relation  consisting  of these  three
tuples, when projected and joined,  yields a tuple not in the original
relation;  i.e., this  decomposition is  not lossless.   Note:  if you
don't trust the  use of abstract symbols, replace  each of the symbols
a, a2, etc., by a distinct integer.

Problem #22: Oracle TYPEs, TABLEs and SELECT
Correct: a) Only I

    I SELECT rr.d.a FROM R rr ;
      is okay as R has an alias "rr" whose members rr.d.a are SELECTed.

   II SELECT d.a FROM R ;
      will cause an error in Oracle because it expects an alias for R.   

  III SELECT a FROM THE(SELECT d FROM R) ;
      will produce errors for two reasons:
        - the sub-query (SELECT d FROM R) requires that R be given
          some alias, e.g., SELECT rr.d FROM R rr.
        - the overall SELECT also requires that THE(...) be aliased,
          e.g., SELECT xx.a FROM THE(...) xx.

Thus, only I produces no error in Oracle.          

Problem #23: E1, E2, ... E10 isa Hierarchy
Correct: b) 10

Let us denote the entity sets by E(1), E(2), ... E(10).

For 1 <=  i <= 10, if e  belongs to E(i), then e also  belongs to each
entity set in the set {E(1),  E(2), ... E(i-1), E(i)}.  Since i ranges
from   1   thru    10,   there   can   only   be    ten   such   sets.

Problem #24: OQL query over Team and Player
Correct: a)

(b) is incorrect because p. playsFor is a team object, not a collection,
and therefore cannot appear in the FROM clause.

(c) is incorrect because t.players is a collection, and thus cannot be
extended by a dot to t.players.playsFor.

(d) is incorrect for a similar reason.

Problem #25: E/R diagram with A(50), B(20), C(200) and R
Correct: c) 1000

R has two functional dependancies: AB -> C and AC -> B.

Consider tuples in R with the first attribute A = a.
If (a, b, c) is a tuple,
  - there cannot be another tuple (a, b', c) with b <> b'
  - there cannot be anotehr tuple (a, b, c') with c <> c'
Effectively, there is a "pairing" of  b and c.

Since B has 20 entities while C  has 200, there can be at most 20 such
pairs (minimum of 20 and 200 is 20).

Thus, any  particular value of  A = a  can be associated with  only 20
pairs of the form (b, c). Since there are 50 distinct values of A, the
total size of R can be at most 50 x 20 = 1000 tuples.

Problem #26: Three manager-queries in Datalog
Correct: d) I, II and III

All three queries can be expressed in Datalog:

  I Highest (m, e)             <-- Emps (e, s, m) AND MaxSalary (s, m)
    Max_Salary (s, m)          <-- Emps (_, s, m) AND NOT Less_Than_Max_Salary (s, m)
    Less_Than_Max_Salary(s, m) <-- Emps (_, s, m) AND Emps(_, t, m) and s < t
    
 II Reports (m, e) <-- Emps (e, _, m)
    Reports (m, e) <-- Reports (m, f) AND Emps (e, _, f)

III MgrOfMgrOfMgrOf (e, m) <-- Emps (e, _, x) AND Emps (x, _, y) AND Emps (y, _, m)    

Problem #27: Three manager-queries in SQL
Correct: c) I and III only

  I Less_Than_Max_Salary (m, s) = PROJECT_(E1.salary, E1.manager)       (SELECT_(E1.manager = E2.maanger AND E1.salary < E2.salary)  (E1 x E2))
    Max_Salary (s, m)           = PROJECT_(Emps.salary, Emps.manager)   (SELECT_(Emps.manager = Less_Than_Max_Salary.manager AND  Emps.salary <> Less_Than_Max_Salary.salary) (Emps x Less_Than_Max_Salary))
    Highest (m, e)              = PROJECT_(Emps.manager, Emps.employee) (SELECT_(Emps.salary = Max_Salary.salary AND  Emps.manager = Max_Salary.manager) (Emps x Max_Salary))

    where E1 and E2 are the same Emps relation twice.
          
 II Cannot  be expressed in  core relational algebra.  Intuitively, we
    need "recursion" to reach the (manager of)^* of an employee.
  
III PROJECT_(E1.eName, E3.manager)  (SELECT_((E1.manager = E2.eName) AND (E2.manager = E3.eName)) (E1 x E2 x E3))

    where E1, E2 and E3 are the same Emps relation three times.


Problem #28: Privileges for INSERT with REFERENCES
Correct: b) REFERENCES on Manfs

We  need REFERENCES  on Manfs  (to be  able to  check  the referential
integrity constraint) and INSERT on Beers  (to be able to insert a new
tuple into Beers).

Note that  SELECT on  Beers or Manfs  is not  necessary as we  are not
evaluating any (sub)-query that involves either table. UPDATE on Beers
is  also not  needed as  that  privelege enables  "update of  existing
tuples"; our need is "insertion of new tuples".

Problem #29: GRANT/REVOKE privileges
Correct: b)

Following the convention in  the DB textbook, the GRANT/REVOKE diagram
at the end of the first four GRANT statements has four nodes:

  (a)  A(INSERT on R, **)
  (b)  B(INSERT ON R, *)
  (c)  C(INSERT ON R, *)
  (d)  D(INSERT ON R, *)

There are four edges:

   (i)  A(INSERT on R, **) --->  B(INSERT ON R *)
  (ii)  B(INSERT on R, *)  --->  C(INSERT ON R *)
 (iii)  C(INSERT on R, *)  --->  D(INSERT ON R *)
  (iv)  D(INSERT on R, *)  --->  B(INSERT ON R *)

The  double star denotes  ownership of  relation. Single  stars denote
"WITH GRANT OPTION".

When B  revokes privilege from C,  edge (ii) gets  deleted. This means
node (c)  and edge  (iii) also get  deleted.  Since CASCADE  option is
specified, any other node not  reachable from A (the owner of relation
R,  are deleted.   This means  that node  (d) and  edge (iv)  also get
deleted. This leaves us with two nodes A(INSERT on R, **) and B(INSERT
on R, *) with an edge from A to B.

Problem #30: JDBC statement
Correct: a) myStat.setInt(1, 2) ;

To replace tuple  (1, 1) by (2,  1), we would like to  execute the SQL
statement "UPDATE R SET a = 2 WHERE b = 1".

We already have PreparedStatement myState with one parameter (question
mark  placeholder)  denoted by  a  "?". To  be  able  to execute  this
statement,  we first  need to  set  the question  mark placeholder  by
"myStat.setInt (1,  2) ;".  After  setting this value, we  would write
"myStat.executeUpdate() ;" to actually carry out the update.

A tutorial covering JDBC PreparedStatement is available here).

Problem #31: Bag vs set semantics
Correct: c) R U S

(a) T = R - S

    Irrespective of whether we employ bag or set semantics,
    
      (i) If a tuple occurs in both R and S, it is not part of T,
     (ii) if there is a tuple in R but not in S, exactly one copy is
          part of T
    (iii) if there is a tuple in  S but not in R, it is not part of T.

    The resultant T is the same in both cases.

(b) T = (R JOIN S) - (S JOIN R)

    T  would be empty  irrespective of  whether we  employ bag  or set
    semantics. This is because (R JOIN S) and (S JOIN R) are identical
    sets/bags.

(c) T = R U S

    If a tuple occurs in both R and S, then it occurs twice in T if we
    use bag semantics. Only one occurence occurs in T if we employ set
    semantics.


(d) T = SELECT (a = 5) R

    Selection would produce the same set of tuples since R is a set.

Problem #32 SQL Expression with 3-Valued Logic
Correct: c) TRUE or UNKNOWN, but never FALSE

Note that (X <  Y) OR (X >= Y) is a  tautology that evaluates to TRUE.
However,  SQL  does  not  arrive   at  such  an  answer  by  algebraic
manipulation.    SQL   would   first  evaluate   each   sub-expression
individually  and  then  evaluate   the  truth  value  of  the  entire
expression.  Thus, if X and  Z are both UNKNOWN, the entire expression
evaluates to  UNKNOWN. Note that  there is no  way to make  the entire
expression FALSE.

Thus, the expression can evaluate to either TRUE or UNKNOWN, but never
FALSE.

Problem #33: Answer with Red and Blue
Correct: c) (1, 3)

This is a problem that several people got wrong.

Let's evaluate the two relations first. It is easy to see that

  P(x, y) = {(1, 2), (2, 3), (3, 4), (1, 3), (2, 4), (1, 4)}
  Q(x, y) = {(2, 4), (1, 3)}

We are left with the evaluation of
  Answer(x, y) <- P(x, y) AND NOT Q(y, x)

Now comes  the tricky part: Notice  the order of  x and y in  the rule
"Answer(x,y) <- P(x,y)  AND NOT Q(y,x)".  It turns out  that (1, 3) is
not in Answer(x,y).

Problem #34: Which rule is safe?
Correct: d) P(x, y) <- Q(x) AND R(y) AND x < y AND NOT S(y)

A  Datalog rule  is safe  if every  variable in  a rule  appears  as a
parameter to to some non-negated relational subgoal.

In (a), y does not appear in any relation.
In (b), x does not appear in any relation.
In (c), z does not appear in any non-negated relation.
In (d), all variables: x and y, appear in non-negated relations: Q(x)
        and R(y).

Problem #35: Meaning of ||
Correct: a) Concatenation

In SQL, || denotes the string concatenation operator.

In  some  languages  for  expressing  parallel  programs,  ||  denotes
parallel execution. Example: Occam?

In programming languages like C, || denotes lazy OR.

In  some older programming  languages, ||  denoted eager  OR. Example:
Pascal?