Issues with Group functions - sql

I'm working on lab question that I just cannot come up with a solution, that would allow me to figure out the books that have more then one author(See the posted question below for my comments to make sense). My mind is totally blank on it. I'm very bad with word problems. I know that I have to do a JOIN statement which I've completed and I know that I have to use the COUNT function to count the number of authors but I honestly don't know how I would go about only counting the books that have 2 authors.
Any input would be appreciated. I tried to break it down into steps but it's just that one part that I'm not grasping in my mind.
Using the correct tables in your schema, create a query using either join operation you wish that will list the book title and number of authors for all books that have been written by more than one author. Give the title column an alias of "Book Title" and the column showing the number of authors an alias of "Number of Authors".
There is a BOOKS table and a AUTHOR table that are JOINED by a BOOK_AUTHOR table by their BOOKID in BOOKS and AUTHORID in AUTHOR.
I think I'm starting to understand that I have to use a mathematical equation to figure out more then one author. I don't understand the HAVING function all too well so I'm going to do more research on this one.

You were right, you need a JOIN, a COUNT, but also an HAVING to make sure there is more then one authors that written the book :
select title as 'Book Title', count(authors) as 'Number of Authors'
from books
join authors on books.id = authors.book_id
having count(authors) > 1
group by authors;
Make sure to adapt the table names and columns to the right one, as you didn't post them.
Note that if the books's author id column has the same name as the author id, you can use the USING keyword to join. then your query would become
select title as 'Book Title', count(authors) as 'Number of Authors'
from books
join authors on using(book_id)
having count(authors) > 1
group by authors;
Note that if you want to select only books that specifically have 2 authors you can change the having clause to having count(authors) = 2. But even if you ask for that in your question, according to the exercice you pasted, you did not understand properly the question.

I finally figured out the answer with all your help. Please see below:
SELECT DISTINCT Title "Book Title", COUNT(*)"Number of Authors"
FROM BOOKS JOIN
BOOK_AUTHOR ON
BOOKS.BookId = BOOK_AUTHOR.BookId
JOIN AUTHOR ON
BOOK_AUTHOR.AuthorId = Author.AuthorId
GROUP BY Title
HAVING COUNT(*) > 1;

Related

Solving an sqlplus query

Given below are two relation schemas:
Book(id, title, author, pubid, year, price, referid)
Publisher(pubid, pubname, headoffice, contact)
'id' is the primary key for Book and pubid is the primary key for 'Publisher' as well as a foreign key.
Q. Find the book id, title, referenced title and referenced publisher name.
help me answer this query...I'm trying hard but to no avail
This seems like a homework question and not like you've invested much time into solving this query on your own but this should get you started. Please edit your question to clarify if it's something more specific you're having issues:
SELECT
Book.id,
Book.title,
Publisher.pubname
FROM Book
INNER JOIN Publisher
ON Book.pubid = Publisher.pubid
This query should do
SELECT Book.id, Book.title, Refbook.title, Refpub.pubname
FROM Book
LEFT JOIN Book AS Refbook ON Book.referid = Refbook.id
JOIN Publisher AS Refpub ON Refpub.pubid = Refbook.pubid
For the next time, please give example data and a result you're looking for

Select name for authors that havent written a book

We have to select authors that havent written a book but there are 3 different tables which makes me confused about how to write the join expression.
We have tables:
authors: author_id
authorships: author_id, book_id
books: book_id.
Obviously I selected the names from authors and tried inner join but it wont work for me. Help would be appreciated!
Since this sounds like a school assignment I won't give the full answer.
Try using an outer join between authors and authorship. Make sure you retrieve the book I'd from the authorship.
Try to work out what an author who has not published looks like the. You can use this to formulate the query for the answer you are looking for with an appropriate where clause.
This is a good spot to use the LEFT JOIN antipattern:
SELECT a.*
FROM authors a
LEFT JOIN authorships s ON s.author_id = a.author_id
WHERE s.author_id IS NULL
Rationale: when the LEFT JOIN comes up empty, it means that the author has no corresponding record in the authorships table. The WHERE clause filters out on unmatched authors records only (ie authors that have no books). This is called an antipattern because the purpose of a JOIN is usually to match records, whereas here we use it to detect unmatched records.
Its really easy, just check which column seems to be having common value between all this three tables if something is common atleast within two tables then put inner join on those two and an outer join on the uncommon data table.
Remember your Aliases will always matter when you join between different tables, also the ON and WHERE should be properly mentioned.

SQL count column rows that is dependent on a column in different table when group by

I have been trying to complete the following assignment:
Write a query that returns authors who've written books in more than one category and whose books are published by at least two different publishers. Display the author's Last Name and First Name, the Titles of Books they've written and the Book type. Sort the output by the author's last name.
These are the tables involved:
AUTHORS (Au_id, Au_lname, Au_fname, Phone, Address, City, State, Country, Postalcode)
PUBLISHERS (Pub_id, Pub_name, City, State)
TITLES (Title_id, Title, Type, Pub_id, Price, Advance, Total_sales, Notes, Pubdate, Contract)
TITLEAUTHOR (Au_id, Title_id)
I was able to identify the columns I need, but am not sure how to implement the filters (2 different authors, 2 different types). I assume I need to group by author id and count the Pub_id and Type columns.
This is what I have written so far:
SELECT AUTHORS.Au_lname, AUTHORS.Au_fname, TITLE.Title_id, TITLE.Type
from AUTHORS
JOIN TITLEAUTHOR ON AUTHORS.Au_id = TITLEAUTHOR.Au_id
JOIN TITLE ON TITLEAUTHOR.Title_i = TITLE.Title_i
group by AUTHORS.Au_lname, AUTHORS.Au_fname, TITLE.Title_id, TITLE.Type
ORDER BY AUTHORS.Au_lname;
Welcome to Stack Overflow, Tomasz! Congratulations on your first post. You've done a couple of excellent things already:
You included details on your schema
You included a clear problem statement
You included an example of the SQL you have already tried.
There are a couple of ways you could improve your post, which would help your chances of getting a good answer while also boosting your ability to participate in the community:
Be very careful with formatting - your second edit introduced some redundant text.
Be particular with your code - the first set you gave had some incorrect column names, which likely caused some users to look at your post and then ignore it. There's a critical window after you first post a question where it shows up near the top of the list; that's your best shot at getting answers, so it pays to be very careful with your presentation. Here's a link to some good reading on how to ask.
Be upfront about it when you're working on an assignment! As you can imagine, this community gets a lot of requests for help on homework. Many of the regular users get frustrated by people looking to 'cheat' on their assignments by posting their homework online. There are ways to get help, though: read this post over carefully so you're ready for your next question. The keys are to show that you've already tried to solve it yourself, be specific about what's not working, and be clear about the fact that this is homework.
Now, about your question! What you are looking for is the HAVING clause, which allows you to filter a query to return only those members of a group who meet a condition at the aggregate level. Your instinct about a COUNT was right on, and the HAVING clause will let you do that. Here's an example:
SELECT Au_id
FROM
AUTHORS
INNER JOIN
TITLEAUTHOR ON
AUTHORS.Au_id = TITLEAUTHOR.Au_id
INNER JOIN
TITLES ON
TITLEAUTHOR.Title_id = TITLE.Title_id
GROUP BY Au_id
HAVING
COUNT(DISTINCT TITLES.pub_id) > 1 AND
COUNT(DISTINCT TITLES.Type) > 1
Notice that this adds the word DISTINCT inside of the COUNT() function - this helps you meet the "two different publishers" requirement.
Once you understand how to use HAVING, then you can write a query to get the columns your assignment asked for, and filter the set to only return authors you want: the basic query structure is going to look like this:
SELECT MyColumns
FROM MyTables
WHERE Au_id IN
(
SELECT Au_id
FROM
AUTHORS
INNER JOIN
TITLEAUTHOR ON
AUTHORS.Au_id = TITLEAUTHOR.Au_id
INNER JOIN
TITLES ON
TITLEAUTHOR.Title_id = TITLE.Title_id
GROUP BY Au_id
HAVING
COUNT(DISTINCT TITLES.pub_id) > 1 AND
COUNT(DISTINCT TITLES.Type) > 1
)
ORDER BY WhateverYouWant
Good luck, and welcome to SQL!

SQL, using data from a number of separate tables to receive an output

So my tables I'm working with look like the following:
Book(BookID, Title)
Author(BookID, AuthID)
Writer(AuthID, PubID, FirstName, LastName)
Publisher(PubID, PubName, Country)
And I'd love to change them to make more sense, but I'm not allowed to even change their names at this point.
Anyway, I have two separate pieces of code that I want to run together. So it's the result of this:
select Book.Title
from Book
join Author
on Book.BookID=Author.BookID
group by Book.Title, Book.BookID
having count(*) >= 2
with this:
select AuthorID
from Author
join Publisher
on Author.PubID=Publisher.Publisher
where Publisher.Country like 'Australia'
Initially I thought INTERSECT might work but I quickly realised that because they're not matching fields, I need something else. And the fact that Writer and Publisher have to be linked via Author is throwing me off completely.
Is there a way to do this save going back to the table and changing it to something less unnecessarily complex?
I've been going through the list of statements and whatnot on trying to find a solution, but I'm not sure which one I'm supposed to be looking at. Perhaps something with GROUP in it? So anything, just a point in the right direction would be much appreciated.
Are you trying to find all books with more than one author published in Australia?
If so, the query would look something like this:
select b.Title
from Book b join
Author a
on b.BookID = a.BookID join
Writer w
on w.AuthId = a.AuthId join
Publisher p
on w.PubId = p.PubId
where p.Country like 'Australia'
group by b.Title, b.BookID
having count(*) >= 2;
I think there's a small conceptual misunderstanding blocking your way here.
The two queries can be combined into a single query, and return the results you want, via multiple joins involving all these tables.

need help with mysql for book system - problem with where clause

hello all im developing new project for publisher ...this project for develop system saved all books for that publisher ...............
we have 3 table
books
author
coauthor
problem case:
ieach book have 1 main author thats author could replay in alot of books and ieach book in some cases could have co-author this co author could be 1 or 2 or 3 or 12 note: this co author is already saved in author table
realtionship:
one to many between authors and books
many to many between coauthor and books and authors
table #1 authors table => table hold all authors
id - author_name
table #2 books table => table hold all books
id- title - author_id - publishing_year
table #3 co_authors table => hold all item which have alot of co author
item_id and authors_id
now how i can retrive all books for specific author if he is main author or co author
There're two ways you can go about this... One is to use a UNION, so something like:
SELECT id FROM books WHERE author_id = ?
UNION ALL
SELECT item_id FROM co_authors WHERE authors_id = ?
Another way you could solve this is to rework your database structure such that there is no author_id in the books table and instead you have a flag in co_authors called main_author or some such. Considering you may have books where it's unclear who the main author is, this may make more sense...
You can do something like this :
SELECT DISTINCT books.*, authors.*
FROM books
LEFT JOIN co_authors ON co_authors.item_id = books.id
INNER JOIN authors ON
authors.id = books.author_id OR
authors.id = co_authors.author_id
WHERE authors.id = ID
The where clause can also be written where authors.name = 'NAME' if you need to search by name and not id.
EDIT: added distinct to avoid multiple rows for the same book.