SQL join and MySQL - mysql

In my database I have these tables
products
-------------
id | title |
-------------
1 Cheese
2 Milk
3 Water
etc .....
products_to_city
-----------------------
city_id | product_id |
-----------------------
1 1
1 2
2 3
3 1
3 1
I am using this sql query to fetch the result
SELECT
p.id,
p.title
FROM products p
LEFT JOIN products_to_city ptc ON ptc.id = 1
The problem is that the query above fetches all data from table instead of only where city is 1
What am I doing wrong ?

You didn't tell the query what to join products and products_to_city on. Especially with the LEFT JOIN which will force a result set to include every record in products for every record in products_to_city. I think you want this:
SELECT p.id, p.title
FROM products p
INNER JOIN products_to_city ptc
ON p.id = ptc.product_id
WHERE
ptc.city_id = 1

use this:
SELECT
p.id,
p.title
FROM products p
INNER JOIN products_to_city ptc ON ptc.id = p.id
where ptc.id = 1

You aren't joining products to city, you are getting a match of all the products and city.
SELECT
p.id,
p.title
FROM products p
LEFT JOIN products_to_city ptc ON ptc.product_id = p.id
where ptc.city_id = 1

You're doing an outer join, so where no match is made, you get the row returned anyway. Consider an inner join.

Replace LEFT JOIN with JOIN
That's because LEFT JOIN took even the rows (at the left of the join) that haven't a corrisponing key into the right table.
The JOIN tooks only the colum from "left" and "right" tables that satisfies the pk and fk match
So this will be your solution
SELECT
p.id,
p.title
FROM products p
JOIN products_to_city ptc ON ptc.id = 1

see Basic Question : LEFT OUTER JOIN vs Left Join, (http://stackoverflow.com/questions/2809594/basic-question-left-outer-join-vs-left-join)
they are the same.
you want left inner join.

LEFT JOIN products_to_city ptc ON p.id = ptc.id

When you do this
LEFT JOIN products_to_city ptc
you're telling MySQL (all SQL dbms, actually) to return all the rows from products, even if they don't match the join condition.
To return only those rows that match the join condition, use
INNER JOIN products_to_city ptc ON ptc.product_id = p.id AND (something else)
Note that you need to join the tables using the right column names.
I'm not sure what you want in that "something else" clause, because something like you wrote--pct.id = 1--is normally something you might express in a WHERE clause. The problem is that the products_to_city table doesn't have any column named "id".

Related

mysql distinct query returning more than 1 result

I'm expecting for one product along with it's title and due amount. this query however is not efficient. Not sure with what i'm missing here. Any help would be appreciated
SELECT DISTINCT p.product_title, po.qty, co.due_amount
FROM pending_order po
LEFT JOIN products p ON p.product_id = po.product_id
LEFT JOIN customer_orders co ON po.invoice_no = co.invoice_no
LEFT JOIN customers cs ON cs.customer_id = co.customer_id
WHERE co.invoice_no = '1355021133'
the result i'm getting

Filter on Many to Many relationship

I have 3 tables product, filter, product_filter - Many to Many relationship
I'm trying to filter products like this:
SELECT p.* FROM product p
INNER JOIN product_filter pf ON pf.product_id = p.id
WHERE (pf.filter_id = 1 OR pf.filter_id = 2) AND pf.filter_id = 3
The problem is that there are products that have all the filters(1,2,3) but i get 0 results
Please help :)
For a given row in the cross product there is only one filter_id. You don't have 1 and 3 in the same row in product_filter.
To get that effect try a double join along these lines :-
SELECT p.* FROM product p
INNER JOIN product_filter pf1 ON pf1.product_id = p.id
INNER JOIN product_filter pf2 ON pf2.product_id = p.id
WHERE (pf1.filter_id = 1 OR pf1.filter_id = 2) AND pf2.filter_id = 3

mysql query joining tables to create newsfeed

I want to retrieve rows from 3 tables - LikeTable, ClosetTable, FollowTable to display the activities of all the users a person is following. This is for a website. ClosetTable is the table for the user's products. LikeTable is the table for the likes of the products and Followtable for the following and followers.
Currently, I have
SELECT c.user, c.productName
FROM ClosetTable AS c
LEFT JOIN FollowTable AS f ON c.user = f.isFollowed
WHERE f.follows = 'tony'
This returns the rows of the person, 'tony' is following together with the productname. However, I want rows from the LikeTable and FollowTable in the same manner altogether. So can you suggest a way to do only 1 query to get rows from all 3 tables?
You can try something that look like this :
SELECT c.user, c.productName
FROM FollowTable AS f
INNER JOIN ClosetTable AS c ON c.user = f.isFollowed
INNER JOIN LikeTable AS l ON c.user = l.userliked
WHERE f.follows = 'tony'
I do some assumption for fields name since you didn't provide the structures of your tables.
Also, I suggested that you put the FollowTable in the FROM clause and then join it to ClosetTable since you put f.follows = 'tony' in your WHERE clause.
Otherwise, remove the WHERE clause and put the condition in the INNER JOIN.
Something like :
LEFT JOIN FollowTable AS f ON c.user = f.isFollowed AND f.follows = 'tony'
More JOINs:
SELECT c.user, c.productName
FROM ClosetTable AS c
LEFT JOIN FollowTable AS f ON c.user = f.isFollowed
JOIN LikeTable as l on c.user = l.liked
WHERE f.follows = 'tony'
or something like that. You aren't restricted to one JOIN.

Mysql: How to get values from other table base from an id

Assuming that I have 3 tables on my database
Table:Category
category_id
Table:container
container_id
category_id
Table:products
container_id
product_id
How do you get all product_id based on a category_id?
For example I have these data inside my tables from above:
Table: category
sour
sweet
Bitter
Table: container
bottled
sachet
Table: product
sugar
vinegar
cocoa
How do you get all Product(tb_product) where category(tb_category) is sweet
You can use INNER JOIN to solve your problem.
SELECT a.*
FROM products a
INNER JOIN container b
on a.container_id = b.container_ID
INNER JOIN Category c
ON b.category_ID = c.categoryID
WHERE c.categoryName = 'sweete'
As you can see, I assume that the Category table has columns category_ID and categoryName. So in my example above,I've use category name to search for all products that belong on certain category.
select p.*
from Category c
join container c2 on c2.category_id = c.category_id
join product p on p.container_id = c2.container_id
where c.name = 'sweet';
Note the order of the tables in the query (which should perform faster than the other answer!)
you can use inner join like this:
SELECT a.product_id FROM products AS a INNER JOIN container AS b on a.container_id = b.container_Id INNER JOIN Category AS c on b.category_Id = c.category_id where c.category_id = 'new'

SQL 'Not in' query involving three tables

I have three tables, product, category and product_to_category. Product has the primary key product_id, category category_id and product_to_category p2c_id. Product_to_ category links products to categories in a many-to-many relationship using their respective ID's.
Basically I want to write a query that would select all products from categories that do not exist in the category table. This is due to products being migrated across from another database.
I had something like this but was a little lost.
SELECT *
FROM product AS p
LEFT JOIN product_to_category AS p2c ON p.product_id = p2c.product_id
LEFT JOIN category AS c ON c.category_id
Basically that is as far as I have got. I need to join the category table to the product_to_category table where the product_to_category category_id is not in the category table. I may be completely on the wrong path but am stuck!
Thanks in advance.
Assumption: A product can be part of categories that exist, categories that do not exist, or no categories at all. You have not asked for products that belong to no categories at all, so the first LEFT JOIN from product to procduct_to_category should be an INNER JOIN.
Caveat: I am rusty at mysql so I am using SQL SERVER syntax. I forget if mysql has ON clauses or uses where clauses for JOINs. If ON clause is not supported, change them into WHERE clauses.
There are two common approaches: OUTER JOIN or a NOT IN clause (or a NOT EXISTS clause, which often behaves the same performance-wise as the NOT IN clause.)
OUTER JOIN
select p.*, p2c.category_id
from product p
INNER JOIN product_to_category p2c ON (p.product_id = p2c.product_id)
LEFT JOIN category c ON p2c.category_id = c.category_id
WHERE c.category_id IS NULL
The test for null will find the unmatched records.
NOT IN clause
SELECT p.*, p2c.category_id
FROM product p
INNER JOIN product_to_category p2c ON (p.product_id = p2c.product_id)
WHERE p2c.category_id NOT IN (SELECT c.category_id FROM category c)
If you're looking for products from nonexistent categories, I'd suggest
Select p.*,p2c.category_id
from product p
join product_to_category p2c
on p.product_id=p2c.product_id
left outer join category c
on p2c.category_id=c.category_id
where c.category_id is null
SELECT p.*
FROM product AS p
LEFT JOIN product_to_category AS p2c ON p.product_id = p2c.product_id
WHERE NOT EXISTS (
SELECT 1
FROM category c
WHERE c.category_id = p2c.category_id
)
SELECT *
FROM product AS p
JOIN product_to_category AS p2c ON p.product_id = p2c.product_id
JOIN category AS c ON c.category_id != as.category.
Try this?