Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion Query question, Need to write a query that returns only the students that have read all books by an author.
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Charles Hooper  
View profile  
 More options Jun 8 2007, 9:27 pm
Newsgroups: comp.databases.oracle.misc
From: Charles Hooper <hooperc2...@yahoo.com>
Date: Fri, 08 Jun 2007 18:27:24 -0700
Local: Fri, Jun 8 2007 9:27 pm
Subject: Re: Query question, Need to write a query that returns only the students that have read all books by an author.
On Jun 8, 5:56 pm, Albright.Br...@gmail.com wrote:

> I need to write a query that returns only the students that have read
> all books by an author.  I have these tables set up so far....

> create table Books (
>         BookTitle varchar2(20) PRIMARY KEY,
>         author varchar2(20)
> );

> create table BookCamp (
>         MemberName varchar2(20),
>         BookTitle varchar2(20),
>         CONSTRAINT fk_BookTitle
>           FOREIGN KEY (BookTitle)
>           REFERENCES Books(BookTitle)
> );

> insert into Books values ('Psycho', 'Brian');
> insert into Books values ('Happy Rotter', 'Rocksteady');
> insert into Books values ('Goblet', 'J.K Rowling');
> insert into Books values ('Prisoner', 'J.K Rowling');

> insert into BookCamp values ('Bob', 'Psycho');
> insert into BookCamp values ('Chuck', 'Goblet');
> insert into BookCamp values ('Chuck', 'Prisoner');
> insert into BookCamp values ('Mike', 'Psycho');
> insert into BookCamp values ('Mike', 'Goblet');
> insert into BookCamp values ('Mike', 'Prisoner');
> insert into BookCamp values ('Mary', 'Goblet');

> So basically, if I inputted "J.K Rowling" the names "Chuck" and "Mike"
> should come up.  If the author is "Brian" then the names "Bob" and
> "Mike" should come up.  I've tried several things like...
> select membername from BookCamp where BookTitle in(select BookTitle
> from Books where (author = 'J.K Rowling')); but this obviously isn't
> quite there....Any Help?

Posting the table definitions and insert statements is a significant
help (note to future posters).

Maxim has provided a solution that produces the desired list.  Let's
see if we can develop another method to solve this problem.  First, a
simple experiment using the analytical version of COUNT:
SELECT
  B.BOOKTITLE,
  B.AUTHOR,
  COUNT(B.BOOKTITLE) OVER (PARTITION BY B.AUTHOR) NUM_BOOKS
FROM
  BOOKS B
WHERE
  B.AUTHOR='J.K Rowling';

BOOKTITLE            AUTHOR                NUM_BOOKS
-------------------- -------------------- ----------
Prisoner             J.K Rowling                   2
Goblet               J.K Rowling                   2

Not too impressive yet, but let's add in the second table:
SELECT
  BC.MEMBERNAME,
  B.BOOKTITLE,
  B.AUTHOR,
  COUNT(DISTINCT B.BOOKTITLE) OVER (PARTITION BY B.AUTHOR)
AUTHOR_NUM_BOOKS,
  COUNT(BC.BOOKTITLE) OVER (PARTITION BY BC.MEMBERNAME, B.AUTHOR)
MEMBER_NUM_BOOKS
FROM
  BOOKS B,
  BOOKCAMP BC
WHERE
  B.AUTHOR='J.K Rowling'
  AND B.BOOKTITLE=BC.BOOKTITLE(+);

Note that I changed the original COUNT(B.BOOKTITLE) to COUNT(DISTINCT
B.BOOKTITLE) and changed the alias to AUTHOR_NUM_BOOKS:
MEMBERNAME           AUTHOR_NUM_BOOKS MEMBER_NUM_BOOKS
-------------------- ---------------- ----------------
Chuck                               2                2
Mary                                2                1
Mike                                2                2
Mike                                2                2
Chuck                               2                2

Now, we need a way to first eliminate all rows where AUTHOR_NUM_BOOKS
is not equal to MEMBER_NUM_BOOKS, and then return a list of names
without duplicates.  This can be accomplished by sliding the above SQL
statement into an inline view:

SELECT DISTINCT
  MEMBERNAME
FROM
  (SELECT
    BC.MEMBERNAME,
    COUNT(DISTINCT B.BOOKTITLE) OVER (PARTITION BY B.AUTHOR)
AUTHOR_NUM_BOOKS,
    COUNT(BC.BOOKTITLE) OVER (PARTITION BY BC.MEMBERNAME, B.AUTHOR)
MEMBER_NUM_BOOKS
  FROM
    BOOKS B,
    BOOKCAMP BC
  WHERE
    B.AUTHOR='J.K Rowling'
    AND B.BOOKTITLE=BC.BOOKTITLE(+))
WHERE
  AUTHOR_NUM_BOOKS=MEMBER_NUM_BOOKS;

MEMBERNAME
--------------------
Chuck
Mike

Let's try again, this time without analytical functions.  First, let's
find out how many of the author's books were read by each membername:
SELECT
  BC.MEMBERNAME,
  B.AUTHOR,
  COUNT(*) MEMBER_NUM_BOOKS
FROM
  BOOKS B,
  BOOKCAMP BC
WHERE
  B.AUTHOR='J.K Rowling'
  AND BC.BOOKTITLE=B.BOOKTITLE
GROUP BY
  BC.MEMBERNAME,
  B.AUTHOR;

MEMBERNAME           AUTHOR               MEMBER_NUM_BOOKS
-------------------- -------------------- ----------------
Mike                 J.K Rowling                         2
Chuck                J.K Rowling                         2
Mary                 J.K Rowling                         1

Now, let's determine the number of books written by each author:
SELECT
  AUTHOR,
  COUNT(*) AUTHOR_NUM_BOOKS
FROM
  BOOKS
GROUP BY
  AUTHOR;

AUTHOR               AUTHOR_NUM_BOOKS
-------------------- ----------------
Rocksteady                          1
Brian                               1
J.K Rowling                         2

Let's put each into an inline view and pull out the membernames of
interest:
SELECT DISTINCT
  BC.MEMBERNAME
FROM
  (SELECT
    BC.MEMBERNAME,
    B.AUTHOR,
    COUNT(*) MEMBER_NUM_BOOKS
  FROM
    BOOKS B,
    BOOKCAMP BC
  WHERE
    B.AUTHOR='J.K Rowling'
    AND BC.BOOKTITLE=B.BOOKTITLE
  GROUP BY
    BC.MEMBERNAME,
    B.AUTHOR) BC,
  (SELECT
    AUTHOR,
    COUNT(*) AUTHOR_NUM_BOOKS
  FROM
    BOOKS
  GROUP BY
    AUTHOR) B
WHERE
  B.AUTHOR=BC.AUTHOR
  AND B.AUTHOR_NUM_BOOKS=BC.MEMBER_NUM_BOOKS;

MEMBERNAME
--------------------
Chuck
Mike

Let's try one more time, A simple starting point:
SELECT
  BC.MEMBERNAME,
  COUNT(BC.BOOKTITLE)
FROM
  BOOKS B,
  BOOKCAMP BC
WHERE
  B.AUTHOR='J.K Rowling'
  AND B.BOOKTITLE=BC.BOOKTITLE(+)
GROUP BY
  BC.MEMBERNAME;

MEMBERNAME           COUNT(BC.BOOKTITLE)
-------------------- -------------------
Chuck                                  2
Mary                                   1
Mike                                   2

[The above does not need to be an outer join]
Now, let's add an inline view to retrieve the total number of books
written by the author:
SELECT
  BC.MEMBERNAME,
  COUNT(BC.BOOKTITLE) MEMBER_NUM_BOOKS,
  NB.AUTHOR_NUM_BOOKS
FROM
  BOOKS B,
  BOOKCAMP BC,
  (SELECT
    COUNT(*) AUTHOR_NUM_BOOKS
  FROM
    BOOKS
  WHERE
    AUTHOR='J.K Rowling') NB
WHERE
  B.AUTHOR='J.K Rowling'
  AND B.BOOKTITLE=BC.BOOKTITLE(+)
GROUP BY
  BC.MEMBERNAME,
  NB.AUTHOR_NUM_BOOKS;

MEMBERNAME           MEMBER_NUM_BOOKS AUTHOR_NUM_BOOKS
-------------------- ---------------- ----------------
Chuck                               2                2
Mike                                2                2
Mary                                1                2

The final clean up is accomplished with a HAVING clause:
SELECT
  BC.MEMBERNAME
FROM
  BOOKS B,
  BOOKCAMP BC,
  (SELECT
    COUNT(*) AUTHOR_NUM_BOOKS
  FROM
    BOOKS
  WHERE
    AUTHOR='J.K Rowling') NB
WHERE
  B.AUTHOR='J.K Rowling'
  AND B.BOOKTITLE=BC.BOOKTITLE(+)
GROUP BY
  BC.MEMBERNAME,
  NB.AUTHOR_NUM_BOOKS
HAVING
  COUNT(BC.BOOKTITLE)=NB.AUTHOR_NUM_BOOKS;

MEMBERNAME
--------------------
Chuck
Mike

Charles Hooper
IT Manager/Oracle DBA
K&M Machine-Fabricating, Inc.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.