I'm new to this, so I know I'm missing something simple, but I can't figure it out. I'm trying to join 3 tables together and I've got it working with 2 joins, but when combined in the same query, there ends up being an error.
My 3 tables are:
TBL_Authors
Author_ID
Author_Name
TBL_Publishers
Publisher_ID
Publisher_Name
TBL_Books
Title
Author_ID
Publisher_ID
ISBN
Genre
Price
Cost
Rating
What I have that isn't working:
$query = 'SELECT * FROM TBL_PUBLISHERS
JOIN TBL_BOOKS ON TBL_PUBLISHERS.Publisher_ID = TBL_BOOKS.Publisher_ID
SELECT * FROM TBL_AUTHORS
JOIN TBL_BOOKS ON TBL_AUTHORS.Author_ID = TBL_BOOKS.Author_ID
ORDER BY TBL_BOOKS.Title ASC;';
This query assumes that each book was published.
SELECT
*
FROM
TBL_Books b
INNER JOIN TBL_Publishers p ON b.Publisher_ID = p.Publisher_ID
INNER JOIN TBL_Authors a ON b.Author_ID = a.Author_ID
ORDER BY
b.Title
Book will always have an Author, but not necessarily a Publisher, if it's not published. If you need to fetch all the books irrespective of whether published or not, you will have to change INNER join on TBL_Publishers to LEFT.
This Query Will show you the result of all details of book, publisher name, author name.
SELECT
t1.* , t2.Publisher_Name , t3.Author_Name
FROM
TBL_Books as t1
INNER JOIN TBL_Publishers as t2 ON t1.Publisher_ID = t2.Publisher_ID
INNER JOIN TBL_Authors as t3 ON t1.Author_ID = t2.Author_ID
ORDER BY
t1.Title
Check This and update if this query helps you.
Related
My goal is to get all records from tables where foreign key values match with IDs returned by a subquery from another table.
I have tried several combinations of but they don't even compile.
To clarify, consider following query:
SELECT *
FROM `news`
WHERE IDFIRM IN (SELECT ID FROM firm WHERE Block=0)
AND Actual=1
This is a simple query, but besides the ID in this subquery, I need to also retrieve other columns and return them in response.
Something like this (but of course this doesn't work):
SELECT news.*, sub.name
FROM `news`,
(SELECT * FROM firm WHERE Block=0) AS sub
WHERE news.IDFIRM IN (SELECT sub.ID FROM sub)
AND news.Actual=1
I have an idea how to implement this using joins, but the problem is that there can be multiple IN statements (from different tables), like this:
SELECT *
FROM `news`
WHERE IDFIRM IN (SELECT ID FROM firm WHERE Block=0)
AND Actual=1
AND id_publisher IN (SELECT ID FROM publisher WHERE Block=0)
So this query can become quite different, depending on the request.
How can I create the most efficient query to solve this task? Or it is possible only with multiple queries?
Thanks.
You should definitely use JOIN instead of IN (SELECT ...):
Query 1:
SELECT *
FROM `news`
WHERE IDFIRM IN (SELECT ID FROM firm WHERE Block=0)
AND Actual=1
Replace this by:
SELECT news.*
FROM news
INNER JOIN form ON news.IDFIRM = form.ID
WHERE news.Actual=1
Query 2:
SELECT news.*, sub.name
FROM `news`,
(SELECT * FROM firm WHERE Block=0) AS sub
WHERE news.IDFIRM IN (SELECT sub.ID FROM sub)
AND news.Actual=1
Replace by:
SELECT news.*,
firm.name
FROM news
INNER JOIN firm ON news.IDFIRM = firm.ID
WHERE news.Actual=1
AND firm.Block=0
Query 3:
SELECT *
FROM `news`
WHERE IDFIRM IN (SELECT ID FROM firm WHERE Block=0)
AND Actual=1
AND id_publisher IN (SELECT ID FROM publisher WHERE Block=0)
Replace by:
SELECT news.*
FROM news
INNER JOIN firm ON news.IDFIRM = firm.ID
INNER JOIN publisher ON news.id_publisher = publisher.ID
WHERE news.Actual=1
AND firm.Block=0
AND publisher.Block=0
Adding tables and conditions
So the idea is that you add all the tables you need with clauses like this:
INNER JOIN table1 ON news.<foreign-key> = table1.ID
and that you add the conditions all in the WHEREclause, like this:
WHERE table1.field = <literal>
AND table2.field = <other literal>
AND ...
Assuming your your indexes are sane on both sides of the JOIN they will actually be leveraged, whereas subqueries might use one side.
SELECT [column_list]
FROM news n
INNER JOIN firm f
ON n.idfirm = f.id
INNER JOIN publisher p
ON n.idpublisher = p.id
WHERE n.actual = 1
AND f.block = 0
AND p.block = 0
You are already suggesting a JOIN.
You can use multiple JOIN's to get what you want.
SELECT * FROM news
JOIN firm ON IDFIRM = firm.ID
WHERE Block = 0
JOIN publisher ON id_publisher = publisher.ID
WHERE Block = 0
I'm doing this from memory but should get you close I think.
I am trying to figure out
(book_id, branch_id, total_copies, number_available)
Here is the schema:
Here is as far I have gone:
SELECT
TITLE,
A.BOOK_ID,
A.BRANCH_NAME,
A.BRANCH_ID,
NO_OF_COPIES,
COUNT(BOOK_LOANS.BOOK_ID) AS NUM_OUT,
NO_OF_COPIES - COUNT(BOOK_LOANS.BOOK_ID) AS NUM_AVAIL,
AUTHOR_NAME
FROM
(SELECT
TITLE,
BOOK.BOOK_ID,
BOOK_COPIES.BRANCH_ID,
BRANCH_NAME,
NO_OF_COPIES,
BOOK_AUTHORS.AUTHOR_NAME
FROM
BOOK,
BOOK_COPIES,
LIBRARY_BRANCH,
BOOK_AUTHORS
WHERE
BOOK_COPIES.BOOK_ID=BOOK.BOOK_ID
AND BOOK_AUTHORS.BOOK_ID = BOOK.BOOK_ID
AND (
BOOK.TITLE LIKE :title
OR BOOK.BOOK_ID = :book_id
OR BOOK_AUTHORS.AUTHOR_NAME LIKE :author_name
)
AND BOOK_COPIES.BRANCH_ID=LIBRARY_BRANCH.BRANCH_ID) AS A
LEFT OUTER JOIN
BOOK_LOANS
ON A.BOOK_ID=BOOK_LOANS.BOOK_ID
AND A.BRANCH_ID=BOOK_LOANS.BRANCH_ID
GROUP BY
A.BOOK_ID,
A.BRANCH_ID
But the problem I am encountering is, since BOOK_AUTHORS table has multiple authors for a single book. So I am able to understand that joining only on book_id of BOOK and BOOK_AUTHORS while I should be able to completely using the both book_id and author_name.
So its returning the count 2 times for a single entry in book_loans.
e.g. If a book with book_id lets say 1234 is checked out once, and it has total copies of 2, so it should return remaining copies as 1. But its returning 0.
Please help me understand how to fix this.
Note: I am using php prepare statement.
I didn't pay attention on you query (too complicated to me),
COUNT(DISTINCT BOOK_LOANS.BOOK_ID) rather than COUNT(BOOK_LOANS.BOOK_ID). If you query works well except its count, DISTINCT is helpful.
performance matters. I guess inline view is too complicate. I wonder if changed like this
SELECT
DISTINCT BOOK.BOOK_ID
FROM
BOOK INNER JOIN BOOK_AUTHORS USING(BOOK_ID)
WHERE
BOOK.TITLE LIKE :title
OR BOOK.BOOK_ID = :book_id
OR BOOK_AUTHORS.AUTHOR_NAME LIKE :author_name
Then final query looks like this
SELECT
TITLE,
BOOK.BOOK_ID,
LIBRARY_BRANCH.BRANCH_NAME,
LIBRARY_BRANCH.BRANCH_ID,
BOOK_COPIES.NO_OF_COPIES,
COUNT(distinct BOOK_LOANS.BOOK_ID) AS NUM_OUT,
BOOK_COPIES.NO_OF_COPIES - COUNT(distinct BOOK_LOANS.BOOK_ID) AS NUM_AVAIL,
AUTHOR_NAME
FROM
(
SELECT
DISTINCT BOOK.BOOK_ID
FROM
BOOK,
BOOK_AUTHORS
WHERE
BOOK.TITLE LIKE :title
OR BOOK.BOOK_ID = :book_id
OR BOOK_AUTHORS.AUTHOR_NAME LIKE :author_name
) AS A
INNER JOIN BOOK USING(BOOK_ID)
INNER JOIN BOOK_AUTHORS USING (BOOK_ID)
INNER JOIN BOOK_COPIES USING(BOOK_ID)
INNER JOIN LIBRARY_BRANCH USING(BRANCH_ID)
LEFT OUTER JOIN
BOOK_LOANS
ON BOOK.BOOK_ID=BOOK_LOANS.BOOK_ID
AND LIBRARY_BRANCH.BRANCH_ID=BOOK_LOANS.BRANCH_ID
GROUP BY
BOOK.BOOK_ID,
LIBRARY_BRANCH.BRANCH_ID,
LIBRARY_BRANCH.BRANCH_NAME,
BOOK_COPIES.NO_OF_COPIES,
AUTHOR_NAME
I have the following tables:
table name -----| table fields
books -------------| book_id, book_title
authors ---------- | author_id, author_name
books_authors - | author_id, book_id
users ------------- | user_id, user_name
comments -------- | comment_id, comment
comments_users | comment_id, user_id, book_id, date
I need to show the book title, its authors, and all the comments posted for this book (I need to show user name, date, comment).
I make do it with two different sql queries, but I don't know how to do it with just 1 query.
Here are the two queries:
SELECT * FROM books
INNER JOIN books_authors
ON books.book_id=books_authors.book_id
INNER JOIN authors
ON books_authors.author_id=authors.author_id
WHERE books.book_id=7
this one returns the name and authors of book with id=7.
SELECT `user_name`, `comment`, `date`
FROM comments_users
INNER JOIN comments ON comments_users.comment_id = comments.comment_id
INNER JOIN users ON comments_users.user_id = users.user_id
WHERE comments_users.book_id=7
this one returns the user name, comment, and the date the comment was posted.
Can anyone explain me how can I join them into one query? Thanks in advance
This arranged query should suffice, it will display results as you want :
SELECT books.book_title, authors.author_name, comments.comment FROM books
INNER JOIN books_authors
ON books.book_id=books_authors.book_id
INNER JOIN authors
ON books_authors.author_id=authors.author_id
LEFT JOIN comments_users ON comments_users.book_id = books.book_id
INNER JOIN comments ON comments_users.comment_id = comments.comment_id
INNER JOIN users ON comments_users.user_id = users.user_id
WHERE books.book_id=7
Can't you just JOIN all the tables from the two queries?
SELECT `books.book_id`, `books.book_title`, `comments_users.user_name`,
`comments_users.comment`, `comments_users.date`
FROM books
INNER JOIN books_authors ON books.book_id=books_authors.book_id
INNER JOIN authors ON books_authors.author_id=authors.author_id
INNER JOIN comments_users ON comments_users.book_id = books.book_id
INNER JOIN comments ON comments_users.comment_id = comments.comment_id
INNER JOIN users ON comments_users.user_id = users.user_id
WHERE books.book_id=7
Hope this is what you're trying to achieve.
I have the following query which works perfectly:
SELECT *
FROM contacts
WHERE id in (
SELECT DISTINCT contacts.id
FROM contacts
INNER JOIN contacts2tags
ON contacts.id = contacts2tags.contactid
WHERE tagid in(7,4)
)
Here contacts table contains id, first_name, last_name, ..and tags table contains id, name. contacts2tags table contains contactid and tagid which are same as contacts.id and tags.id respectively
Now, what I want is, to display only the contacts which have both a tagid 7 and a tagid 4.
I tried something like this:
SELECT *
FROM contacts
WHERE id IN
(
SELECT CT1.contactid
FROM
tags T1, contacts2tags CT1, tags T2, contacts2tags CT2
WHERE CT1.contactid = CT2.contactid
AND CT1.tagid = T1.id
AND CT2.tagid = T2.id
AND (T1.id = 7 AND T2.id = 4)
and it works too.
My problem is, I want to convert the above second query to one using inner joins.
I have an array of ids stored in $tmp in php
I want to use those ids and write the above query for them.
How do I do that? I am not comfortable with sql. Might be its a very simple thing to ask.
Thanks in advance
EDIT:
The answer below solved the problem. But the sql runs very slow for 10k records. Any suggestions to optimise it? Pasting the updated query as given in the answer.
SELECT c.id
FROM contacts c
inner join contacts2tags t on c.id = t.contactid
where t.tagid in (7,4)
group by c.id
having count(distinct t.tagid) = 2
This should work
SELECT c.id
FROM contacts c
inner join contacts2tags t on c.id = t.contactid
where t.tagid in (7,4)
group by c.id
having count(distinct t.tagid) = 2
I am a little bit rusty on my SQL and would like some help with these queries that I am struggling getting my head round or even finding out if it is possible.
Hi so I have some tables;
clients,products,clientproducts
when a client opts in for a product that is added to clientproducts, using the clientid and the productid.
the easy query
I want to run a query that will only show me products the client has opted in for.
the harder one
I also want to run a query that will show me just the clients that haven't opted in for a product/s.
Thank you for your help in advance.
Query 1:
SELECT table1.id1 FROM table1
WHERE table1.id1 IN (SELECT table2.foreign_id FROM table2);
Query 2:
SELECT table1.id1 FROM table1
WHERE table1.id1 NOT IN (SELECT table2.foreign_id FROM table2);
here, use LEFT JOIN
SELECT a.*
FROM products a
LEFT JOIN clientproducts b
ON a.productID = b.productID
LEFT JOIN clients c
ON b.clientID = c.clientID AND
c.ClientID = 'clientID HERE'
WHERE c.client IS NULL
OR
SELECT a.*
FROM products a
LEFT JOIN clientproducts b
ON a.productID = b.productID AND
b.ClientID = 'clientID HERE'
WHERE b.productID IS NULL
The easy query
SELECT * FROM clients LEFT JOIN products ON clients.id = products.client_id
The hard query
SELECT * FROM clients WHERE clients.id NOT IN (SELECT clients.id FROM clients LEFT JOIN products ON clients.id = products.client_id)
Get all the products information where client_id = 1
select products.*
from products, clientproducts
where products.id = clientproducts.product_id
and clientproducts.client_id = 1
Get all the clients details who has not opted for any products
select *
from clients
where id not in (select client_id
from clientproducts)