I have the following tables
Product
id int(11) AUTO_INCREMENT
name varchar(254)
product_category_id int(11)
A Product belongs to a category in ProductCategories. a category has sub category(self join)
id int(11) AUTO_INCREMENT
name varchar(254)
parent_id int(11)
A Product also has a icon stored in ProductMedia.
id int(11) AUTO_INCREMENT
url varchar(254)
type enum('icon','banner','video')
product_id int(11)
What is the most efficient way to get all products with it's associated icon that belong to a category including products in it's sub category if any.
Example:
Product
1. iphone - Mobile(category)
2. sIII - Mobile (category)
3. liginting connector - Cable(category)
4. iPhone USB charger - Charger(category)
ProductCategories
1. Mobile - 0(parent)
2. Cables - 1(parent)
3. Sim - 1
4. Shoes - 0
5. Chargers - 2
When i search for Mobile Category it needs to give me all 4 products, under cable it needs to give last 2 but under charger only last one
Use joins for this
SELECT
p.*,
pc.name,
pm.url,
pm.type
FROM Product as p
LEFT JOIN ProductMedia as pm ON pm.product_id = p.id
LEFT JOIN ProductCategories as pc ON pc.id = p.product_category_id
You can do it like this
EDITS :
select
p.name,
ifnull(pc.Category,pc.name) as Category,
pm.type
from product as p
left join (select
l.id as id,
l.name,
l.parent_id,
if(r.parent_id <> 0,l.name, CONCAT(l.name,'|',r.name )) as Category
from productcategories as l
left join productcategories as r
on r.id = l.parent_id) as pc
on pc.id = p.id
left join productmedia as pm
on pm.product_id = p.id
Output
name | Category | type
----------------------------------------------------------------
iphone | Mobile | banner
sIII | Charger|Mobile | icon
iphone liginting connector | HeadPhones|Mobile | video
You can explode Category with php explode
According to what i got from you question you want something like this.
SELECT
p.*,
m.url,
m.type
FROM Product as p
LEFT JOIN ProductMedia as m ON m.product_id = p.id
LEFT JOIN ProductCategories as c ON c.id = p.product_category_id
where c.id='Mobile'
Related
I have an table called product which lets say looks like this:
product
product_id | cults_id1 | cults_id2 | cults_id3
-----------------------------------------------------
1 | 5 | 4 | 2
And the also a table thats based on this called cultivar:
cultivar
cults_id | cults_name |
-------------------------
1 | berries |
2 | fruit |
3 | choc |
4 | wood |
5 | mysql! |
How would i create an JOIN query to get each name from cultivar table where the product id in product table is the same as cults_id in the cultivar table?
OUTPUT
My Product Cults :
berries, Mysql!, wood, fruit
Dont think an INNER JOIN is the way to go but i would have tried something like this:
$query = "SELECT cultivars.cults_name
FROM product
INNER JOIN wine_cultivar ON wine_cultivar.cults_id = product.cultivar_1_id
INNER JOIN wine_cultivar ON wine_cultivar.cults_id = product.cultivar_2_id
INNER JOIN wine_cultivar ON wine_cultivar.cults_id = product.cultivar_3_id
INNER JOIN wine_cultivar ON wine_cultivar.cults_id = product.cultivar_4_id
";
i tried a inner join multiple times targeting all the ids but dont think this is the way to go. Also this is just a part of my sql query.
Simply assign table aliases to each self join and then reference corresponding fields in SELECT.
Right now you join to same table but do not provide aliases to distinguish between the four which MySQL should have raised its Error #1066 for this attempt.
SELECT p.product_image_path, p.product_id, p.brand_name, p.product_name, b.botttle_size, v.vintage,
t.wine_type_blend, p.price, p.quantity, p.time_created, p.reference_number, p.shipping_cost,
c1.cultivar_type as cultivar_type1, c2.cultivar_type as cultivar_type2,
c3.cultivar_type as cultivar_type3, c4.cultivar_type as cultivar_type4
FROM product p
INNER JOIN wine_bottle b ON b.bottle_id = p.bottle_id
INNER JOIN wine_vintage v ON v.vintage_id = p.vintage_id
INNER JOIN wine_type t ON t.type_id = p.type_id
INNER JOIN wine_cultivar c1 ON c1.cultivar_id = p.cultivar_1_id
INNER JOIN wine_cultivar c2 ON c2.cultivar_id = p.cultivar_2_id
INNER JOIN wine_cultivar c3 ON c3.cultivar_id = p.cultivar_3_id
INNER JOIN wine_cultivar c4 ON c4.cultivar_id = p.cultivar_4_id
I have a categories table (category_id, category_name) with the following type categories:
Website1
Website2
Product_type1
Product_type2
red
blue
green
wood
plastic
metal
A products table (prod_id, prod_name... etc.) and a link table product_cateogries (id, prod_id, category_id).
I'm trying to run a query to filter these values, but some categories are required, and some are X or X. For example, I want to be able to select all Website1 and Product_type2 products that are either red or blue.
My first thought was that I could IN (Product_type2_id, Website2_id, red_id, blue_id) but that makes Product_type2_id and Website2_id optional when they should be required. And using GROUP BY prod_id HAVING count(distinct category_id) = 4) ensures all colours_id are found, when a product can only have one colour. Is a subquery needed somehow?
TABLES:
category:
id (int)
category_name (varchar)
product_category:
id (int)
product_id, (int)
category_id (int)
Products:
prod_id (int)
prod_image
prod_price
SQL Fiddle:
http://sqlfiddle.com/#!9/32ec8
UPDATE:
The below query now does exactly what I want, seems a little messy though and like there should be a cleaner way?
SELECT p.*
FROM products p
LEFT JOIN product_category pc_w1 ON pc_w1.product_id = p.prod_id AND pc_w1.category_id = 3
LEFT JOIN product_category pc_pt2 ON pc_pt2.product_id = p.prod_id AND pc_pt2.category_id = 1
LEFT JOIN product_category pc_rb ON pc_rb.product_id = p.prod_id AND pc_rb.category_id IN (11)
LEFT JOIN product_category pc_rb1 ON pc_rb1.product_id = p.prod_id AND pc_rb1.category_id IN (1,12)
WHERE
pc_w1.product_id IS NOT NULL AND pc_pt2.product_id IS NOT NULL AND
(
pc_rb.product_id IS NOT NULL AND
pc_rb1.product_id IS NOT NULL
)
GROUP BY p.prod_id
Just use joins
SELECT p.*
FROM products p
LEFT JOIN product_category pc_w1 ON
pc_w1.product_id = p.prod_id AND pc_w1.category_id = 3
LEFT JOIN product_category pc_pt2 ON
pc_pt2.product_id = p.prod_id AND pc_pt2.category_id = 7
LEFT JOIN product_category pc_rb ON
pc_rb.product_id = p.prod_id AND pc_rb.category_id IN (9,13) -- black/blue
WHERE
pc_w1.product_id IS NOT NULL OR
(
pc_pt2.product_id IS NOT NULL AND
pc_rb.product_id IS NOT NULL
)
GROUP BY p.prod_id
Edit: I see you added fiddle so here is my working example http://sqlfiddle.com/#!9/837872/4
While creating a local movie database, I have 3 tables with below structure:
TABLE1: movies
movie_id | movie_title
TABLE2: categories
category_id | category_title
TABLE3: categories_movies
id | movie_id | category id
1 movie can have multiple categories, I'm trying to display each movie with its categories, example:
MOVIE TITLE 1 (Category 1, Category 2, Category 3)
MOVIE TITLE 2 (Category 2, Category 3)
Currently I do with 3 queries, first I select all movies:
select * from movies
Then
select * from categories_movies where movie_id = $movie_id
Then
select * from categories where category_id = $category_id
I've tested with some inner join, but no good idea, since 1 movie can have multiple categories.
Any suggestion will help, thanks.
I didn't fully understand what is the format you want to display it, but you can use GROUP_CONCAT() if you want to display it as 1 column:
SELECT m.movie_title,GROUP_CONCAT(c.category_title)
FROM movies m
INNER JOIN categories_movies cm
ON m.movie_id = cm.movie_id
INNER JOIN categories c
ON cm.category_id = c.category_id
GROUP BY m.movie_title
If you just want them to be displayed as separate rows:
SELECT m.movie_title,c.category_title
FROM movies m
INNER JOIN categories_movies cm
ON m.movie_id = cm.movie_id
INNER JOIN categories c
ON cm.category_id = c.category_id
i think you need to use left join :
SELECT m.movie_title,c.category_title
FROM movies m
LEFT JOIN categories_movies cm
ON m.movie_id = cm.movie_id
LEFT JOIN categories c
ON cm.category_id = c.category_id
SELECT movies.movie_title, GROUP_CONCAT(`category_title` SEPARATOR ',') as category
FROM `categories_movies`
left join categories on categories.category_id=categories_movies.category
left join movies on movies.movie_id=categories_movies.movie_id
GROUP BY categories_movies.movie_id
You can use GROUP_CONCAT().It works perfectly:
SELECT movies.movie_title, GROUP_CONCAT( categories.category_title )
FROM movies
INNER JOIN categories_movies ON movies.movie_id = categories_movies.movie_id
INNER JOIN categories ON categories_movies.category_id = categories.category_id
GROUP BY movies.movie_title;
i am using a category , product relation to find data. I am in situation like i have a category table and product table with categoryid and product type. No suppose i have a particular type and i want to find those category which a product of a specific type does not have.
Table struture are like
Category Table
____________
|Id|Category|
| 1| X |
_____________
Product Table
____________________________
|ID | Product|Category| Type|
| 1 | Y | 1 | 2 |
_____________________________
I can find it by using a sub query like
SELECT *
FROM category
WHERE id NOT IN(SELECT category
FROM product
WHERE type = 2);
Is there a way to get it by another way
I also use a JOIN like
SELECT *
FROM category AS c
JOIN products AS p
ON c.id <> p.category
WHERE p.type = 2
Why does this not give the appropriate result.
Use LEFT JOIN and use IS NULL predicate:
SELECT *
FROM category AS c
LEFT JOIN products AS p
ON c.id = p.category
AND p.type = 2
WHERE p.category IS NULL;
The unmatched rows from the second table will have null values in the category field, the WHERE p.category IS NULL will filter and give you them
I want only those products which satisfies following condition :
Which have ((category_id = 1 OR category_id = 2) AND (category_id = 3 OR category_id = 4))
Database structure:
products
id int(10)
name varchar(128)
categories
Id int (10)
name varchar(64)
category_products
product_id int(10)
category_id int(10)
Data:
My product details are:
Products:
id name
1 P1
2 P2
3 P3
4 P4
My category details are:
Categories:
Id name
1 C1
2 C2
3 C3
4 C4
My category-product mapping details are:
category_products:
product_id category_id
1 1
1 3
1 4
2 2
3 1
3 2
3 3
3 4
4 1
4 4
Final Output should be:
id
1
3
4
SELECT DISTINCT p.id, p.name FROM products AS p
INNER JOIN category_products AS c1 ON c1.product_id=p.id
INNER JOIN category_products AS c2 ON c2.product_id=p.id
WHERE c1.category_id IN (1,2) AND c2.category_id IN (3,4)
It wouldn't work to use
WHERE c.category_id IN (1,2) AND c.category_id IN (3,4)
because a WHERE clause tests just one row at a time, and there's no way one category_id can have two values on a single row. So the self-join handles that, by matching more than one row and referencing them by correlation names.
Try this:-
select *
from products
where id in (select distinct(product_id)
from category_products
where (category_id =3 0R category_id=4)
AND (category_id =1 OR category_id=2))
SELECT p.product_id AS id FROM product_categories AS p
WHERE (p.category_id=1 OR p.category_id=2) AND (p.category_id=3 OR p.category_id=4) GROUP BY p.category_id
Because you don't need the name of the product you don't need an INNER JOIN. GROUP BY and DISTINCT should both work.