Joins using Sub Queries - sql

I have two tables named "Book" and "Author." The attributes for the "Book" table are: PK- Book_Num, Book_Title, Book_Year, Book_Cost, Book_Subject. The attributes for the "Author" table are PK- Au_ID, Au_Fname, Au_Lname. These two tables have a M:N relationship with each other and the bridge table between them is named "Writes" and it has a composite primary key from the two tables made up of Book_Num and Au_ID. Here's my question: I want to write a query to display the Au_ID, Au_Fname, Au_Lname for all authors that have never written a book with the subject "Programming" and order the results by Au_Lname. How would I go about doing this with a sub-query?

Give this a shot:
SELECT A.Au_ID, A.Au_Fname, A.Au_Lname FROM Author A
JOIN Writes W ON A.Au_ID = W.Au_ID
JOIN Book B ON B.Book_Num = W.Book_Num
WHERE A.Au_ID NOT IN (
SELECT A.Au_ID FROM Author A
JOIN Writes W ON A.Au_ID = W.Au_ID
JOIN Book B ON B.Book_Num = W.Book_Num
WHERE B.Book_Subject = 'Programming'
)
ORDER BY A.Au_Lname ASC;

If you want better performance,you can use "NOT EXISTS" to get the data you want.
SELECT Au_ID, Au_Fname, Au_Lname FROM Author
WHERE NOT EXISTS
(
SELECT A.Au_ID FROM Author A
JOIN Writes W ON A.Au_ID = W.Au_ID
JOIN Book B ON B.Book_Num = W.Book_Num
WHERE B.Book_Subject = 'Programming'
AND Author.Au_ID = A.Au_ID
)
ORDER BY Au_Lname ASC

Related

How to use Sql join to include a specific column from another table

I have two tables, author and book. Author contains the columns (isbn, name, city, state) and book contains (isbn, title, publisher, category, price, units)
For my assignment I need to output name, city and state (from the author table) and title (from the book table) only for authors from Exeter, NH, Palo Alto, CA, or Arlington, TX.
I can't get join part to work without an error popping up
SELECT
NAME,
city,
state
FROM
author
left JOIN book
USING (title);
WHERE
(city = 'exeter'AND state = 'NH') OR
(city = 'arlington'AND state = 'TX') OR
(city ='palo alto' AND state = 'CA');
What is your DBMS?
you need a field to relate the 2 tables, I suppose it is the ISBN that is the only one in common... (although as they already asked you why the ISBN is in the author?)...
SELECT a.NAME, b.title,a.city,a.state
FROM author a
LEFT JOIN book b
ON a.isbn = b.isbn
WHERE (a.city = 'exeter'AND a.state = 'NH')
OR (a.city = 'arlington'AND a.state = 'TX')
OR (a.city ='palo alto' AND a.state = 'CA')
Left outer join should work so long as you join on the columns shared by the tables.
SELECT a.name
,a.city
,a.state
,b.title
FROM author a
LEFT OUTER JOIN book b on a.isbn = b.isbn
WHERE

Select information from 3 tables in SQL

I have three tables in a SQLite database: book, author and loaned_books. They look like this
book: _id | author_id | title | subject
author: _id | first_name | last_name
loaned_books: _id | book_id | loan_date | due_date
The author_id is a foreign key for the author table, and the book_id is a foreign key for the book table.
I am trying to create a query that extracts all the books (with their associated author) which are not loaned. So far, I have this query:
SELECT book.title, book.subject, author.first_name, author.last_name
FROM book, author
INNER JOIN loaned_books ON book._id != loaned_books.book_id AND book.author_id = author._id
This one does the job with the exception that all the records returned are duplicated. I have tried using DISTINCT on the column names, but the result is wrong as well.
What would be a query that returns all the books (with their associated author) that are not loaned?
The way you join book and author:
FROM book, author
is wrong because it returns the cartesian product of the 2 tables.
You need a LEFT JOIN to loaned_books and return the non matching rows (meaning the books that don't exists in loaned_books)
SELECT b.title, b.subject, a.first_name, a.last_name
FROM book AS b
INNER JOIN author AS a ON b.author_id = a._id
LEFT JOIN loaned_books AS l ON b._id = l.book_id
WHERE l._id IS NULL
Could you please try executing this:
SELECT distinct book.title, book.subject, author.first_name, author.last_name
FROM book inner join author on book.id = author._id left outer join loaned_books ON book._id = loaned_books.book_id where loaned_books.book_id is null or length(loan_date) = 0 or loan_date = ''

Borrowers who borrowed ONLY all books of a specified author and editor

For a given author and editor, i need to list names of borrowers who borrowed "ONLY" "ALL" the books of that author and editor
MEMBER (mid primary key, name, birthdate)
AUTHOR (authorcode primary key,name)
EDITOR(edcode primary key,name)
BORROW (bid primary key, copyid, mid)
COPIES (copyid primary key, bookid)
BOOK (bookid primary key, title, themecode)
THEME (themecode primary key, label)
I tried the following:
SELECT m.name
FROM MEMBER m,COPIES c,BORROW b1,BOOK b,AUTHOR a,EDITOR e,WRITE w
WHERE m.mid=b1.mid AND b1.copyid=c.copyid AND c.bookid=b.bookid AND b.editor=e.edcode AND a.authorcode=w.author AND w.book=b.bookid
MINUS
(SELECT m.name
FROM MEMBER m,COPIES c,BORROW b1,BOOK b,AUTHOR a,EDITOR e,WRITE w
WHERE m.mid=b1.mid AND b1.copyid=c.copyid AND c.bookid=b.bookid AND b.editor=e.edcode AND a.authorcode=w.author AND w.book=b.bookid AND (a.authorcode<>:P58_AUTHOR OR e.edcode<>:P58_EDITOR)
)
It gave me a member who borrowed at least one book and didnt borrow any book other than that author and editor , so I need to make sure he borrowed all the books
I think the following will give you what you need:
WITH book_ed_auth_dets AS (SELECT b.bookid,
a.authorcode,
e.edcode,
COUNT(*) OVER (PARTITION BY a.authorcode, e.edcode) tot_num_bks_per_auth_ed
FROM book b
INNER JOIN WRITE w ON b.bookid = w.book
INNER JOIN author a ON w.author = a.authorcode
INNER JOIN editor e ON b.editor = e.edcode
WHERE a.authorcode = :p58_author
AND e.edcode = :p58_editor)
SELECT m.name
FROM MEMBER m
INNER JOIN borrow b1 ON m.mid = b1.mid
INNER JOIN copies ON c.bookid ON b1.copyid = c.copyid
INNER JOIN book_ed_auth_dets bead ON c.bookid = bead.bookid
GROUP BY m.id,
m.name,
bead.authorcode,
bead.edcode
bead.tot_num_bks_per_auth_ed
HAVING COUNT(DISTINCT bead.bookid) = bead.tot_num_bks_per_auth_ed);
N.B. Untested, since you didn't provide sample data to work with.
This finds the books for a given author and editor, and uses an analytic count to write out the total number of books for that author and editor for each row.
Then we inner join the member's borrowed books to that, find the count of distinct bookids (in case the member borrowed the same book more than once) and only report members if that count matches the count of books for the author and editor.
If I am not wrong then WRITE table is the most imp table which you missed to describe.
I have taken an idea from your existing query and tried to create the solution as follows:
SELECT
NAME
FROM
(
SELECT
M.NAME,
-- NO OF BOOK BORROWED BY MEMBER OF THAT AUTHOR AND EDITOR
COUNT(DISTINCT B.BOOKID) NO_BOOKS_BORROWED
FROM
MEMBER M
JOIN BORROW B1 ON ( M.MID = B1.MID )
JOIN COPIES C ON ( B1.COPYID = C.COPYID )
JOIN BOOK B ON ( C.BOOKID = B.BOOKID )
JOIN EDITOR E ON ( B.EDITOR = E.EDCODE )
JOIN WRITE W ON ( A.AUTHORCODE = W.AUTHOR )
JOIN AUTHOR A ON ( W.BOOK = B.BOOKID )
GROUP BY
M.NAME
--CONDITION TO CHECK THAT BORROWER HAS NOT BOUGHT ANY OTHER BOOK
HAVING
SUM(CASE
WHEN A.AUTHORCODE <> :P58_AUTHOR
OR E.EDCODE <> :P58_EDITOR THEN 1
END) = 0
) BORRROWER
--
JOIN (
SELECT
-- NO OF ALL BOOKS WRITTEN BY AUTHOR AND EDITOR
COUNT(DISTINCT B.BOOKID) NO_BOOKS_WRITTEN
FROM
EDITOR E
JOIN WRITE W ON ( A.AUTHORCODE = W.AUTHOR )
JOIN AUTHOR A ON ( W.BOOK = B.BOOKID )
WHERE
A.AUTHORCODE = :P58_AUTHOR
AND E.EDCODE = :P58_EDITOR
) AUTHOR_EDITOR ON ( BORRROWER.NO_BOOKS_BORROWED = AUTHOR_EDITOR.NO_BOOKS_WRITTEN )
Cheers!!
The following returns all the books by a given author and editor:
select w.bookid
from book b join
writes w
on b.bookid = w.bookid
where b.edcode = :P58_EDITOR and
w.authorcode = :P58_AUTHOR;
The following finds members who have borrowed all these books:
with bae as (
select w.bookid
from book b join
writes w
on b.bookid = w.bookid
where b.edcode = :P58_EDITOR and
w.authorcode = :P58_AUTHOR
)
select b.mid
from borrow b join
copies c
on c.copyid = b.copyid join
bae
on b.bookid = bae.bookid
group by b.mid
having count(distinct b.bookid) = (select count(*) from bae);
Note that the count(distinct) is needed because a member could, presumably, borrow the same book twice.

Join 3 tables with different FKs

I'm trying to join 3 tables together in a SELECT query with some WHERE clauses.
Table 1 is linked to Table 2, and Table 2 is linked to Table 3.
The tables are as follows:
Author
PK: Author_ID
FK: Location_ID
Author_First_Name
Location
PK: Location_ID
City
Articles
PK: Article_ID
FK: Author_ID
Article_Name
So far I've put together this Query, but am having trouble determining how to to Join the second Foreign Key 'Location_ID'
SELECT
Articles.Article_Name
FROM
Articles
INNER JOIN Author
ON Articles.Author_ID
INNER JOIN Location
ON
WHERE Author.Author_First_Name='Sam'
AND Location.City<>'Detroit'
The proper syntax is something like this:
SELECT a.Article_Name
FROM Articles a INNER JOIN
Author au
ON a.Author_ID = au.Author_ID INNER JOIN
Location l
ON l.Location_ID = au.Location_Id
WHERE au.First_Name = 'Sam' AND l.City <> 'Detroit';
Note the use of table aliases make the query easier to write and to read. Also, you need conditions connecting the two tables for the ON clauses.
You forgot to compare table fields
SELECT * FROM articles ar
LEFT JOIN author a ON ar.author_id = a.author_id
LEFT JOIN location l ON a.location_id = l.location_id
WHERE a.author_first_name = 'Sam' AND l.city <> 'Detroit'

SQL Query Using Data from 2 tables

I have 2 tables: authors and books.
in authors i have attributes authorID, authorName, and authorDOB.
authorID is the primary key in this table.
in the books table i have attributes bookISBN, authorID, etc.
with bookISBN as the primary and authorID as the foreign key
i am trying to perform a query where given an author name, perform a
count of all the books by that author.
here is what i got:
SET #ID =
AuthorID
FROM authors
WHERE ('Mark Twain' = AuthorName);
SELECT COUNT(*)
FROM books
WHERE (AuthorID = ID);
Any help would be greatly appreciated
Try:
SELECT a.authorId, a.authorName, count(*)
FROM authors a
INNER JOIN books b ON b.AuthorID=a.AuthorID
WHERE ('Mark Twain' = a.AuthorName)
GROUP BY a.authorId, a.authorName
i am trying to perform a query where given an author name, perform a count of all the books by that author.
Try
select count(1)
from books b
inner join authors a on a.AuthorID=b.AuthorID
where a.AuthorName='Mark Twain'
You can use a function as well if you think you'd be doing the search more frequently. Just an idea.
go
create function totalbooksbyauthor (#authorname varchar(20) ) returns table
as return
select a.authorid, a.authorname, COUNT(b.bookname) bookcount
from authors a
inner join books b
on a.authorID = b.authorID
where a.authorname = #authorname
group by a.authorid, a.authorname
go
select * from totalbooksbyauthor ('Mark Twain')