I have two tables products and categories. For products I have the ff fields:
id
pname
category_id
date
And for the cateogries id I have:
id
name
So using inner join I am trying to select all the names of categories that are equal to the category_id inside the products table.
Here's my take:
SELECT
c.name
FROM
categories AS c
INNER JOIN products AS p ON c.id = p.category_id
However this one did not work out and it's just sending me an empty array.
Any idea how can I do this? thanks!
If you just want category names, then exists or in is more appropriate than join:
SELECT c.name
FROM categories c
WHERE EXISTS (SELECT 1 FROM products p WHERE c.id = p.category_id);
You will not have to worry about eliminating duplicates, unless two categories have the same name.
This is also much more efficient than using SELECT DISTINCT on your query, especially if products has an index where category_id is the first key.
Related
I am using MySQL to get some additional information from database. I am trying to do widget bar:
Here is table structure:
My query:
SELECT * FROM `product` WHERE category in (SELECT name FROM category where id='5')
What i want is i need to display category names and products numbers.
But above query gives me empty result set. What am i doing wrong ?
Its only my assumption, since there is little info
This query gets a list of categories and for each adds a count of products having id of that category
select c.id, c.name, count(p.id) count
from category c
left join
product p
on p.category = c.id
group by c.id
You will get rows with category id, category name, product count
I have three tables as below, each product may belong to multiple categories.
PRODUCT TABLE AS P
1. ID
2. NAME
CATEGORY TABLE AS C
1. ID
2. NAME
RELATION TABLE AS R
1. ID
2. P_ID
3. C_ID
Now I want to get a list of all products in product table, and with their belonging category name display as well.
How do I write this query?
I can get the category ids pulled from the same query, but don't know how to get all the name pulled as well. Here's what I tried.
select p.*,y.*
from p
left join (select p_id,group_concat(c_id) as category_ids
from relation group by p_id) as y on p.id=y.p_id
Do both JOIN operations (to the relation table, and from there to the table containing the category names) and feed the result to your aggregation function (GROUP_CONCAT)
SELECT P.Name, GROUP_CONCAT(DISTINCT C.Name ORDER BY C.Name SEPARATOR '|') categories
FROM Product P
LEFT JOIN Relation R ON P.ID = R.P_ID
LEFT JOIN Category C ON R.C_ID = C.ID
GROUP BY P.ID, P.Name
This will give you one row per product with the categories separated by |.
This uses LEFT JOIN operations so it won't suppress products that have no categories.
Select P.Name, C.Name
From RELATION R Inner Join PRODUCT P
On R.P_ID=P.Id
Inner Join Category C
On C.Id=R.C_ID
This query will get you all the products, with their corresponding category.
I want to give you a small explanation about the difference between Inner Join and Left Join.
If we take as an example 2 tables :
TA(idA, description) and TB(idB, idA, description).
Select TA.description, TB.description
From TA Inner Join TB On TA.IdA = TB.IdA
will get only the rows in TA, that have a corresponding one in TB.
On the other side,
Select TA.description, TB.description
From TA Left Join TB On TA.IdA = TB.IdA
will get all the rows of TA and if the row in TA doesn't have a corresponding one in TB, TB.description for this row will be NULL.
Hope this helps!
I want to get category id and name from company category table which do not exists in company category cross table. For example the company with id 3 has already category 1 and category 2 and i want the sql result to get category 3
I tried following statement but not getting expected result
SELECT `wp_bmg_company_category`.id, `wp_bmg_company_category`.name
FROM `wp_bmg_company_category`
INNER JOIN `wp_bmg_company_category_cross`
ON `wp_bmg_company_category`.id != `wp_bmg_company_category_cross`.categoryid
if I understood correctly you search category which is now unused.
Select all company data with category ID (return only category ID)
Select all data from category where category id NOT IN (use 1. select data)
And if you find the only unused category for each company separately. Use something like this (ADD company_id for search each company separately, to search unused categories):
SELECT *
FROM category ca
WHERE category_id NOT IN
(SELECT category_id
FROM category c1
JOIN category_cross cc ON c1.id = cc.category_id
WHERE company_id = 1)
What you need is an outer join (left or right) that can retrieve all records from a table, regardless whether it is present in the other table. (You may use not in() or not exists() in place of the outer join).
The other technique you need is called Cartesian join, whereby you match all records from one table with all records from another table. In this case, match all records from the companies table with all records in the categories, to get the complete list of company - category combinations. Then subtract from this the list of categories you have.
select co.id, co.name, ca.id, ca.name
from (wp_bmg_company co join wp_bmg_company_category ca) --this creates the Cartesian join
left join wp_bmg_company_category_cross cr on co.id=cr.companyid and ca.id=cr.categoryid
where cr.id is null --only the non-matched pairs should remain
I have an interesting challenge... I have two tables, products and users.
products contains 2 columns, user_id and current_bidder, which hold two different IDs from the users table.
I would like to select all columns from products, and the name and rating from the users table for each user_id and current_bidder.
Essentially, I'm trying select columns from two different rows on a joined table, while disambiguating their names.
Any help would be greatly appreciated.
Join to the user table twice, and give each copy a different alias. Something like this:
select p.name, p.weight, owner.name, bidder.name
from product p
join user owner
on ...
join user bidder
on ...
The nice way to avoid ambiguity between columns is to add an ALIAS on it.
SELECT a.*, -- selects all records from products
b.name AS user_name, -- user_name is an alias of users.name (user_id)
c.name AS bidder_name -- user_name is an alias of users.name (current_bidder)
FROM products a
LEFT JOIN users b
ON a.user_id = b.id
LEFT JOIN users c
ON a.current_bidder = c.id
The reason why I used LEFT JOIN is because I assumed that some products has no bidder yet. If INNER JOIN was used, product will never be shown on the result until there's a bidder on it.
SELECT *
FROM
productinfo as p ,
category as c
WHERE
c.id IN (p.category) AND
p.pid='T3'
WHERE p.category will return (1,2,3,4,5) from product info table which the id of the category.
Now i need category name used for T3 [product Id] ,but i am getting only the first category name.
Your base query is the following
SELECT * FROM productinfo as p WHERE p.pid = 'T3';
Now you need to pull in categories, per product. This is a many to one relationship, so you need a LEFT JOIN.
SELECT * FROM productinfo as p
LEFT JOIN category as c ON c.id = p.category
WHERE p.id = 'T3'
You need to learn the different types of joins and how they are used. Whenever I see someone use 'FROM table1, table2' 90% of the times it means they don't understand joins and they need a LEFT JOIN instead.
Edit based on your comment
Your datamodel is flawed. Since a product can contain multiple categories, this is really a many-to-many relationship. You should create a product_category table that connects product id's with category id's.