i have a table food
food_id food_name
1 chappathi
and another table category
category_id category_name
1 non-veg
2 nutrition
and a relation table food_category
food_id category_id
1 1
1 2
where the food_id is the foriegn key of food_id in food table, category_id is the foriegn_key of category_id in the category table, there will be case no categories for a food
i have tried
$sql= "SELECT * FROM food f
LEFT JOIN food_category fc
ON f.food_id=fc.food_id
LEFT JOIN category c
ON fc.category_id=c.category_id"
it gives me more than one food items, what i want is
item name: chappathi
categories: non-veg, nutrition
------------------------------
second row of result set if there is any
Try this:
SELECT f.food_name AS item_name, GROUP_CONCAT(c.category_name SEPARATOR ', ') AS categories
FROM food f
LEFT JOIN food_category fc ON f.food_id=fc.food_id
LEFT JOIN category c ON fc.category_id=c.category_id
GROUP BY f.id
Hope it will help you.
Agreed with #strawberry. Look at group_concat.
http://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_group-concat
The query should be written as below to fetch the food name and its categories list.
SELECT f.food_name as ItemName,
STUFF(
(SELECT DISTINCT ',' + c.category_name
FROM food
LEFT JOIN food_category fc on fc.food_id= food.food_id
LEFT JOIN category c ON fc.category_id =c.category_id
FOR XML PATH ('')), 1, 1, '') AS Categories
FROM food f
group by f.food_id, f.food_name
Please check it out.
What you need is group_concat:
SELECT f.food_name, group_concat(c.category_name) AS Cat
FROM food AS f
LEFT JOIN food_category AS fc ON f.food_id = fc.food_id
LEFT JOIN category AS c ON c.category_id = fc.category_id
GROUP BY f.food_id
Related
for this i have 3 tables
categories(id,category)
products(id,category_id,name)
productstock(id,product_id,quantity)
the query written for this
select categories.category,sum(productstock.quantity)
from categories
inner join productStock on products.id=productstock.product_id
inner join products on categories.id=products.category_id
group by category;
it would be a great help
Try using LEFT JOIN.
SELECT c.category, SUM(quantity) AS 'sum_qty' FROM productstock a
LEFT JOIN products b ON a.product_id=b.id
LEFT JOIN categories c ON b.category_id=c.id
GROUP BY category_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;
Let's say i have 3 tables:
table: SONGS
cell: ID primary key
cell: TITLE
cell: ADD_TIME
table: CATEGORIES
cell: ID primary key
cell: title
table: SONGS_CATEGORIES
cell: ID primary key
cell: SONG_ID
cell: CATEGORY_ID
Then let's assume that I have 3 songs(with id's 0, 1, 2), and I have 5 categories(rock, pop, rap and so on) and respectively, their id's(0, 1, 2...). How my sql query should look like, if I want to be able to select more than one category, then I need to look into table SONGS_CATEGORIES and get all songs_id with category id I selected, and then i get songs from table SONGS with those id's?
Hope i explained what i need pretty well, English is not my native language.
If you already know the ID numbers of the categories that you're wanting songs from then the following should do the trick:
SELECT *
FROM SONGS s
JOIN SONGS_CATEGORIES sc
ON s.ID = sc.SONG_ID
WHERE sc.CATEGORY_ID IN (#id1, #id2, #id3...#idN);
If you only know the names of the categories you want the songs for then you can use this:
SELECT *
FROM SONGS s
JOIN SONGS_CATEGORIES sc
ON s.ID = sc.SONG_ID
JOIN CATEGORIES c
ON sc.CATEGORY_ID = c.ID
WHERE c.title IN (#catTitle1, #catTitle2, #catTitle3...#catTitleN);
In both of these examples you would replace the # with the data you are providing and adjust the SELECT part to show only the columns you need.
If you want to select songs from categories 1 & 2 :
SELECT s.id song_id, s.title song_title, s.add_time song_add_time, c.id cat_id, c.title cat_title
FROM CATEGORIES c
INNER JOIN SONGS_CATEGORIES sg
ON c.id = sg.category_id
INNER JOIN SONGS s
ON sg.song_id = s.id
WHERE c.id = 1 OR c.id = 2
I guess this is what you need
SELECT * -- select what ever columns you need to display
FROM SONGS s
JOIN SONGS_CATEGORIES sc
ON s.ID = sc.SONG_ID
JOIN CATEGORIES c
ON c.ID = sc.CATEGORY_ID
where c.title in ('title1','title2')
I got 2 tables:
1 Category
- cID
- Name
- Active
2 Products
- pID
- Name
- category_id
- active
This is want i want:
I want a list from categories that ONLY have ACTIVE products.
Thanks in advance
SOLUTION:
SELECT DISTINCT category.* FROM category INNER JOIN products ON category.id = products.c_id WHERE products.active = 0 ORDER BY category.id DESC
Assume Products.Active = 1 means active state.
SELECT c.*
FROM Category c
INNER JOIN Products p ON c.CID = p.category_id
GROUP BY c.CID
HAVING COUNT(*) = SUM(IF(p.Active = 1, 1, 0))
I'd suggest construction like this
IMHO, it's syntax shows what you really want to see - all categories that have active products
select C.cID, C.Name, C.Active
from Category as C
where C.cID in (select distinct T.category_id from Products as T where T.Active = 1)
SELECT * FROM Products
Join Category on Category.ciD = Products.category_id
WHERE Category.Active = 1 AND Products.Active =1
This is assuming your active columns are just 1 or 0. Otherwise adjust according to what values you're storing there.