Make big query from 3 tables - mysql

I have three tables
profiles (id, name, deleted)
categories (id, name, deleted)
profiles_categories (id, profile_id, category_id, , deleted)
How i can select all profiles with name in categories?
I trying something like this, but its not works...
SELECT *
FROM profiles p
JOIN categories c, profiles_categories pc
WHERE p.id = pc.profile_id
AND WHERE pc.id = c.category_id
Thanks
EDIT
SELECT *
FROM profiles p
INNER JOIN profiles_categories pc
ON p.id = pc.profile_id
INNER JOIN categories c
ON pc.id = c.id
its return only for one profile (now only two active profiles, but only first have categories)

You have several issues with your current query.
First, you are mixing join types. You should use ANSI JOIN syntax between all of the tables. Don't mix ANSI JOIN syntax with some tables and then commas between other tables.
Second, you have two WHERE clauses and you can only have one WHERE clause.
Finally, you should include the column names that you want to return instead of SELECT *
The query should be similar to this:
SELECT p.name, c.name
FROM profiles p
INNER JOIN profiles_categories pc
ON p.id = pc.profile_id
INNER JOIN categories c
ON pc.id = c.category_id
An INNER JOIN between the tables will return all rows that exist in all of the tables.
Note, based on your table structure you might be able to use the following which returns the profiles that have a corresponding row in the the profiles_categories table:
select p.name
from profiles p
where p.id in (select profile_id
from profiles_categories);
Edit you want to return all profiles regardless of whether or not then have a category, then you need to use a LEFT JOIN:
SELECT p.name, c.name
FROM profiles p
LEFT JOIN profiles_categories pc
ON p.id = pc.profile_id
LEFT JOIN categories c
ON pc.id = c.category_id

SELECT *
FROM profiles p
JOIN profiles_categories pc on p.id = pc.profile_id
JOIN categories c on pc.id = c.category_id
or
SELECT *
FROM profiles p, categories c, profiles_categories pc
WHERE p.id = pc.profile_id
AND pc.id = c.category_id

try this:
SELECT *
FROM profiles p
JOIN profiles_categories pr on p.id = pr.profile_id
JOIN categories c on pr.id = c.category_id
WHERE c.name='thename'

Related

How Can I join multiple tables with information i want?

I'm using mysql 8.0.31 version.
Below is my database schema ERD.
I want to get inforamtion about products from my DB.
Below is my sql raw query.
SELECT
p.id, p.name, sc.name sub_category, c.name category, count(po.color_id) color_count
FROM products p
INNER JOIN sub_categories sc
ON sc.id = p.sub_category_id
INNER JOIN categories c
ON sc.category_id = c.id
LEFT JOIN products_options po
ON po.product_id = p.id
INNER JOIN genders g
ON po.gender_id = g.id
WHERE c.id = 1
GROUP BY p.id
ORDER BY p.id ASC;
I want to join products table with sub_categories, categories to get categories information about my products AND products table with products_options, colors, genders to get color_count about a product and gender type about a product.
So I wanted to query like this added g.type (gender type information for a product)
SELECT
p.id, p.name, sc.name sub_category, c.name category, count(po.color_id) color_count, g.type
FROM products p
INNER JOIN sub_categories sc
ON sc.id = p.sub_category_id
INNER JOIN categories c
ON sc.category_id = c.id
LEFT JOIN products_options po
ON po.product_id = p.id
INNER JOIN genders g
ON po.gender_id = g.id
WHERE c.id = 1
GROUP BY p.id
ORDER BY p.id ASC;
But this occurs error like this
SQL Error [1055] [42000]: Expression #6 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'mydb.g.type' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
I think this error occurs cuz I didn't use aggregate function for g.type.
Below is my result except g.type in sql select field.
I want to get genders.type field together.
I think I need to sub query and join that table created by sub query. But I don' t know well How can I implement that method.
To combine this gender type information, How can I modify my sql query?
I tried multiple method sql queries in various ways to join table.
You need to either remove the column from select list like:
SELECT p.id, count(po.color_id) color_count
FROM products p
INNER JOIN sub_categories sc
ON sc.id = p.sub_category_i`enter code here`d
INNER JOIN categories c
ON sc.category_id = c.id
LEFT JOIN products_options po
ON po.product_id = p.id
INNER JOIN genders g
ON po.gender_id = g.id
WHERE c.id = 1
GROUP BY p.id
ORDER BY p.id ASC;
or add in group by clause the select columns like:
SELECT p.id, p.name, sc.name sub_category, c.name category, count(po.color_id) color_count, g.type
FROM products p
INNER JOIN sub_categories sc
ON sc.id = p.sub_category_id
INNER JOIN categories c
ON sc.category_id = c.id
LEFT JOIN products_options po
ON po.product_id = p.id
INNER JOIN genders g
ON po.gender_id = g.id
WHERE c.id = 1
GROUP BY p.id,p.name, sc.name sub_category, c.name category, g.type
ORDER BY p.id ASC;

How to remove a row if sub query returns null value?

I have following query.
select
Product.*,
(
select
group_concat(features.feature_image order by product_features.feature_order)
from product_features
inner join features
on features.id = product_features.feature_id
where
product_features.product_id = Product.id
and product_features.feature_id in(1)
) feature_image
from products as Product
where
Product.main_product_id=1
and Product.product_category_id='1'
I want to bypass the row if feature_image is empty.
Your query looks a bit strange because you are doing most of the work in a subquery:
select p.*, (select group_concat(f.feature_image order by pf.feature_order)
from product_features pf inner join
features f
on f.id = pf.feature_id
where pf.product_id = p.id and pf.feature_id in (1)
) as feature_image
from products p
where p.main_product_id=1 and p.product_category_id='1';
A more common way to phrase the query is as an inner join in the outer query:
select p.*, group_concat(f.feature_image order by pf.feature_order) as feature_image
from products p join
product_features pf
on pf.product_id = p.id and pf.feature_id in (1) join
features f
on f.id = pf.feature_id
where p.main_product_id=1 and p.product_category_id='1'
group by p.id;
This will automatically include only products that have matching features. You would use left outer join to get all products.

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?

Select statement across a join table

Have three tables that look like this:
PersonTable
Person.ID
Person.Name
PersonTypeCompositeTable
Person.ID
PersonType.ID
PersonTypeTable
PersonType.ID
PersonType.Category
For this example, say the values of PersonTypeCompositeTable are:
1,A
2,A
3,B
How to I write a SELECT statement that will return all the people with a PersonType of "A"?
UPDATE: (Working version of answer posted)
SELECT p.*
FROM PersonTable p
INNER JOIN PersonTypeCompositeTable ptc
ON p.ID = ptc.ID
INNER JOIN PersonTypeTable pt
ON ptc.ID = pt.ID
WHERE pt.Category = 'A'
You use joins between the three tables.
SELECT p.*
FROM PersonTable p
INNER JOIN PersonTypeCompositeTable ptc
ON p.Person.ID = ptc.Person.ID
INNER JOIN PersonTypeTable pt
ON ptc.PersonType.ID = pt.PersonType.ID
WHERE pt.PersonType.Category = 'A'

MySQL Join Question

Hi i'm struggling to write a particular MySQL Join Query.
I have a table containing product data, each product can belong to multiple categories. This m:m relationship is satisfied using a link table.
For this particular query I wish to retrieve all products belonging to a given category, but with each product record, I also want to return the other categories that product belongs to.
Ideally I would like to achieve this using an Inner Join on the categories table, rather than performing an additional query for each product record, which would be quite inefficient.
My simplifed schema is designed roughly as follows:
products table:
product_id, name, title, description, is_active, date_added, publish_date, etc....
categories table:
category_id, name, title, description, etc...
product_category table:
product_id, category_id
I have written the following query, which allows me to retrieve all the products belonging to the specified category_id. However, i'm really struggling to work out how to retrieve the other categories a product belongs to.
SELECT p.product_id, p.name, p.title, p.description
FROM prod_products AS p
LEFT JOIN prod_product_category AS pc
ON pc.product_id = p.product_id
WHERE pc.category_id = $category_id
AND UNIX_TIMESTAMP(p.publish_date) < UNIX_TIMESTAMP()
AND p.is_active = 1
ORDER BY p.name ASC
I'd be happy just retrieving the category id's releated to each returned product row, as I will have all category data stored in an object, and my application code can take care of the rest.
Many thanks,
Richard
SELECT p.product_id, p.name, p.title, p.description,
GROUP_CONCAT(otherc.category_id) AS other_categories
FROM prod_products AS p
JOIN prod_product_category AS pc
ON pc.product_id = p.product_id
LEFT JOIN prod_product_category AS otherc
ON otherc.product_id = p.product_id AND otherc.category_id != pc.category_id
WHERE pc.category_id = $category_id
AND UNIX_TIMESTAMP(p.publish_date) < UNIX_TIMESTAMP()
AND p.is_active = 1
GROUP BY p.product_id
ORDER BY p.name ASC
You would use an inner join to the product_category table, doing a left join there is pointless as you are using the value from it in the condition. Then you do a left join on the product_category table to get the other categories, and join in the categories for the data:
select
p.product_id, p.name, p.title, p.description,
c.category_id, c.name, c.title
from
prod_products p
inner join prod_product_category pc on pc.product_id = p.product_id
left join prod_product_category pc2 on pc2.product_id = p.product_id
left join prod_categories c on c.category_id = pc2.category_id
where
pc.category_id = #category_id and
unix_timestamp(p.publish_date) < unix_timestamp() and
p.is_active = 1
order by
p.name