Select books having specified authors - sql

I have Book and Author tables. Book have many Authors (I know that it should be many-to-many it's just for the sake of this example).
How do I select all books that have been written by authors: X and by Y in one sql query?
EDIT
Number of authors can be variable - 3, 5 or more authors.
I can't figure it out now (I've tried to do JOINs and sub-queries).
SELECT * FROM book ...?

Try this:
SELECT
B.Name
FROM Books B
JOIN Authors A
ON B.AuthorID = A.ID
WHERE A.Name IN ('X', 'Y')
GROUP BY B.Name
HAVING COUNT(DISTINCT A.ID) = 2

You can just double join the authors table.
SELECT Book.* from Book
JOIN Author author1
ON author1.book_id = Book.id AND author1.author_name = 'Some Name'
JOIN Author author2
ON author2.book_id = Book.id AND author1.author_name = 'Some Other Name'
GROUP BY Book.id
The JOINs ensure that only books with Both authors are returned, and the GROUP BY just makes the result set only contain unique entries.
It's worth noting by the way that this query will bring back books that have at least the two authors specified. For example, if you want books only by Smith and Jones, and not by Smith, Jones and Martin, this query will not do that. This query will pull back books that have at least Smith and Jones.

select * from book where author=.... ?
I found it hard to understand your structure but this seems like the best way?
Hope this helps

I am assuming that your Author table has a Book ID (as this would give many author to one book).
SELECT * from Books Where ID IN
(SELECT BookID from Author A
JOIN Author B on A.BookID = B.BookID and A.ID <> B.ID
WHERE A.ID IN ('X', 'Y') AND B.ID IN ('X','Y'))
EDIT: Hamlet's answer is much better (scaleable).

Related

Query in a way to show books that belong to different authors

select subject, authors, authorID
from library with (nolock)
inner join authors with (nolock) bookid = bookauthorID
where subject = 'Russian History'
So I want to write a query that will show that all the authors that have written books on Russian History, and I want to show column categoryID as "multiple" if there are more than 2 different authors that written on the subject, and vice versa as "single".
Example:
CategoryID Author
2009940 Steve Cohen
From the above ID, it would return as single, since there's only one distinctive author on this ID.
Would be the best to achieve this using count(min)?
You don't provide a desired output nor do I believe you have shared the appropriate objects for your tables/columns but you can alter this for your needs.
You just need to reference a COUNT(DISTINCT columnName) to see if its greater than 1 or not.
select
subject
, CASE WHEN COUNT(DISTINCT authors) = 1 THEN 'single'
WHEN COUNT(DISTINCT authors) > 1 THEN 'multiple'
END AS Authors
from library
inner join authors bookid = bookauthorID
where subject = 'Russian History'
GROUP BY subject

How do I compare and Select SQL columns between tables

Let's just say that I have a database with 2 tables as follows:
Book (Name, Publisher) and
Publisher (Name, Email)
Now I have a book called Book A with publisher a and publisher a with email sth#gmx.com.
I want the output to be sth#gmx.com i.e., the contact detail(s) of the publisher of said book.
Is there any way to do this if possible? I am new to Sql Server. So, maybe I missed something which is obvious.
The structure would be something like this (based on your explanation):
SELECT v.email
FROM Buch AS b
JOIN Verlag AS v
ON b.verlag = v.name
WHERE b.name = 'Buch A';
To combine results you should use JOIN.
In this case:
Select publisher.Email
From book
Inner join publisher on publisher.name = book.publisher
But you should really use ID's on the rows where the book should store the publishers id as a Foreign key.
So, you are selecting email of a publisher who publishes the Book called A. Based on the above two tables and two columns in each table you may use below query provided Publisher in Book and Name in Publisher table are same.
SELECT p.email FROM Publisher p JOIN Book b
ON b.publisher = p.name WHERE b.name = 'A';
You can try the following using inner join.
create table Book (Name Varchar(50), Publisher Varchar(50))
insert into Book Values ('Book A', 'publisher a')
Create table Publisher (Name Varchar(50), Email Varchar(50))
insert into Publisher Values('publisher a', 'sth#gmx.com')
select Publisher.Email
FROM Publisher
inner join Book on Publisher.Name = Book.Publisher
where Book.Name = 'Book A' and Publisher.Name = 'publisher a'
You can learn about SQL join here
The output is as shown below
Email
-----------
sth#gmx.com
You can find the live demo Live Demo

How do i get results for a search criteria that links to another table?

I am trying to list all book titles given that they have the same authors who wrote the book 'Database principles'. I am not sure on how to link the author who wrote the book to the book title from the table Book and Author. How do i do this?
Assuming that BOOK table has a column AID that is an FK pointing to AUTHORID of the AUTHOR table.
There are many ways of doing so.
Inner Query
SELECT B.* FROM BOOK B WHERE B.AID IN (SELECT AID FROM BOOK WHERE TITLE LIKE '%?%');
Joines
SELECT B1.* FROM BOOK B1 , BOOK B2 WHERE B1.AID = B2.AID AND B2.TITLE LIKE '%?%';
Left outer join
SELECT B1.* FROM BOOK B1 LEFT OUTER JOIN BOOK B2 ON B1.AID = B2.AID WHERE B2.TITLE LIKE '%?%';

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')

In SQL how do you find a row matching one condition, take a value from it and match it to other rows in the same table?

For example if you had a table books and you wanted to find all books by a certain name, then get the author of those books and research the books table for all entries in the table. For instance if you searched the title "All About Pirates" and then there were 2 books with the title, one by "Jane Doe" and another by "Joe Smith" then the table would be searched again for all titles by those authors.
select *
from books b
join books b2 on b.author = b2.author
where title = 'All About Pirates'
Use a sub query like this:
SELECT * FROM books WHERE author IN (SELECT author FROM books WHERE title='All About Pirates');
Your query is almost correct. You need to specify the alias for title in the where clause:
select b2.*
from books b join
books b2
on b.author = b2.author
where b.title = 'All About Pirates'
The original query was not parsable because the title was ambiguous. In this query b2 is the list of books with matching authors.
You can join a table to the results of a select.
For example, you get the author(s) matching the book like this:
SELECT author FROM books WHERE title="All About Pirates" GROUP BY author;
So you can join the books table to this table of authors like this:
SELECT books.*
FROM books
JOIN (SELECT author FROM books WHERE title="All About Pirates" GROUP BY author) AS r
ON books.author=r.author;