This question already has answers here:
Joining three tables using MySQL
(11 answers)
How to join multiple tables in MySQL?
(4 answers)
Closed 3 years ago.
I create a simple data base on 3 tables: Author, that can has many Books, and Genre that also can has many Books.
I want to get all Genres of one Author using it authorId. I wrote next nested SQL select:
SELECT genre.id, genre.genre_id, genre.genre_name, genre.genre_descr FROM (SELECT book.genre_id FROM book WHERE book.author_id = 7654) AS b JOIN genre WHERE b.genre_id = genre.genre_id;
It works good for me, but is it possible some minimize this select? For example, get rid of nested select?
Yes, I know, that the good solution is to create reference many to many beetwen genre and author, but it will add some complications...
Thanks!
You are almost there. A simple join will do
SELECT DISTINCT g.* FROM genre g JOIN book b ON g.id = b.genre_id AND b.author_id = 7654
If you slow reads, then index on author_id should just work.
One possible solution without using join:
select * from genre where id in (select genre_id from book where author_id = 7654)
Related
This question already has answers here:
Select rows which are not present in other table
(4 answers)
Closed 2 years ago.
I have not much experience with JOINS and the result I get with query below isn't correct.
I have a table called products and want to check if there are records in the table product_links.
I only want to get a list of items that doesn't have rows in product_links.
When I run the below query, I only get one line.
Anybody suggestions? Google couldn't help me or I'm searching with the wrong keywords.
SELECT a.id, a.SKU, a.title,
(SELECT COUNT(b.id) AS amount FROM product_links WHERE b.product=a.id) AS amount
FROM products AS a
LEFT JOIN product_links AS b ON b.product=a.id
I would recommend not exists:
select p.*
from products p
where not exists (select 1 from product_links pl where pl.product_id = p.id)
From your question i understand you need info of products which doesnt have any links.
Below is the query for that
SELECT * FROM products
WHERE id NOT IN (SELECT id FROM product_links);
This question already has answers here:
Select values that meet different conditions on different rows?
(6 answers)
Closed 4 years ago.
I'm struggling for hours with something that seems so easy but I cant make it to work or find something similar in Google.
I have 2 tables
images
and
tags
They have a relation of Many to Many so I have another pivot table named image_tag
What Im trying to achive is select all images that has tag_id=4 and tag_id=1
My first attemp was something like this:
SELECT * from images as a INNER JOIN
image_tag as b on a.id=b.image_id
WHERE b.tag_id=4 and b.tag_id=1
Of couse this gave me 0 result as you cant use AND condition directly to pivot.
After that I tried this:
SELECT * FROM images as a
INNER JOIN image_tag as b on a.id=b.image_id
WHERE b.tag_id IN (1,4)
This returns all the images that either has tag_id=1 or tag_id=4 tried also Inner joining the same pivot table but cant make it to work no matter what
EDIT: Adding the sql fiddle. http://sqlfiddle.com/#!9/1726b0/1 the result should be images with ids 4,5,6,7
Use group by and having to get all image_id's meeting the criteria and use the resulting id's for join.
SELECT a.*
FROM images as a
INNER JOIN (select image_id
from image_tag
where tag_id IN (1,4)
group by image_id
having count(distinct tag_id)=2
) b on a.id=b.image_id
You can do this with just the table image_tag. You have to join it with itself in order to get all the combinations. This way you can then select the rows witch will have both tags.
SELECT a.image_id
FROM image_tag as a
inner join image_tag as b on a.image_id=b.image_id
where a.tag_id=4 and b.tag_id=1
This question already has answers here:
SQL query return data from multiple tables
(6 answers)
Closed 6 years ago.
I have a problem here. I created a database with different tables. I have a table named "movie" with 108 movies. This table includes columns
"id, name, director, year, country",
table named "reviews" which includes columns
"movie_id" (movie_id links to the id of movie which was reviewed),
"review_score" (1 to 5 points),
"review (with review text)",
"critics_id" (which links to the critics from critics-table),
and also table named "critics" which icludes columns
"critics_name" and "critics_id".
The problem is that there is over 100 movies but only 10 of them are reviewed and I have to list only reviewed movies but reviews and movies are in different tables. When I try simple command SELECT name, review FROM movie, reviews - I get a huge list with repeating movies (see on picture) my table
Is there any command which could list only reviewed movies and so that every reviewed movie would be in the list only once?
Thanks beforehand!
This is where you use a join. You'd select from the movie table and join the reviews table, then filter by movies that have a joined review.
For example:
SELECT movie.*, review.review_score, review.review
FROM movie
LEFT JOIN reviews AS review
ON review.movie_id = movie.movie_id -- assuming this column name is correct...
WHERE review.movie_id IS NOT NULL
You could also add another join to your critics table:
SELECT movie.*, review.review_score, review.review, critic.critics_name
FROM ....
LEFT JOIN critics AS critic
ON critic.critics_id = review.critics_id
WHERE critic.critics_id IS NOT NULL
Please note that this example uses left join to highlight the way that the join works, in that if it doesn't find a match then the joined result will be null.
If you used an inner join instead, you wouldn't get any results that don't match the on clause, and as such you wouldn't need the WHERE id IS NOT NULL parts at all.
An inner joined example of the above would return movies that are reviewed, as well as the critic's name:
SELECT movie.*, review.review_score, review.review, critic.critics_name
FROM movie
INNER JOIN reviews AS review
ON review.movie_id = movie.id
INNER JOIN critics AS critic
ON critic.critics_id = review.critics_id
Also - I'm using AS to alias the plural table names to a singular name purely for semantic reasons. You could continue to use reviews and critics if you wanted to without the AS aliases.
Hope below query helps you:
SELECT
m.name,
c.critics_name,
r.review_score,
r.review_text
FROM movies m
JOIN reviews r ON r.movie_id = m.id
JOIN critics c ON c.critics_id = r.critics_id
for distinct movies change query as below:
SELECT DISTINCT m.name
FROM movies m
JOIN reviews r ON r.movie_id = m.id
JOIN critics c ON c.critics_id = r.critics_id
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
INNER JOIN ON vs WHERE clause
INNER JOIN:
SELECT *
FROM PETS
INNER JOIN OWNER ON PETS.OWNER_ID = 1
AND OWNER.ID = 1
MULTIPLE TABLE SELECT:
SELECT *
FROM PETS, OWNER
WHERE PETS.OWNER_ID = 1
AND OWNER.ID = 1
Is one better than the other?
Faster than the other?
They seem to produce exactly the same results.
Is there any difference at all?
I am trying to learn the best methods. In using the join, I noticed that the exact same thing can be achieved with the multiple table call
read this answer about the difference between a cross join and an inner join Performance of inner join compared to cross join
This question already has an answer here:
Syntax error due to using a reserved word as a table or column name in MySQL
(1 answer)
Closed 8 years ago.
I have this MySQL query but it seems to be getting an error while I try to run it. Since I'm a newbie I'd like some advice of what I should do to correct it. I just want to show the name, quantity and order date of the orders that has 1 or more pending products. Thanks a lot!
select product.name, order_details.quantity, order.date from product,order_details,order
inner join order on order_details.order_id=order.id
inner join product on order_details.product_id=product.id
inner join customer on order.cust_id=costumer.id WHERE order.pending=>1
You have a table called order. This word has special significance in SQL. Your options are to rename the table, or quote it whenever you want to query from it.
Easiest solution is to change.
inner join order ....
to
inner join `order`
Be sure to use back-quotes around the table name.
You have a table named 'order', which is a reserved word in SQL.
One solution is to prefix the table name with the database name as explained in Craic Computing blog
Another one is to wrap the table name with the ` character as you can read in this StackOverflow question
You can try something like :
SELECT product.name, order_details.quantity, `order`.date
FROM product
INNER JOIN order_details ON product.id = order_detail.product_id
INNER JOIN `order` ON `order`.id = order_detail.order_id
WHERE `order`.pending >= 1
As said in other answers, orderis a reserved keyword in SQL, surround it with backquotes.
Maybe you should store the pending information in the order_detail table (1 if pending, 0 if not), in order to keep track of which product is still pending instead of incrementing/decrementing the order.pending field.
In this case, you could make the following query :
SELECT product.name, order_details.quantity, `order`.date
FROM product
INNER JOIN order_details ON product.id = order_detail.product_id
INNER JOIN `order` ON `order`.id = order_detail.order_id
WHERE `order_detail`.pending = 1
Which would return all the products still pending in your orders instead of every product from orders in which maybe only one is pending.