I can't obtain the result I want, let me explain:
I have two tables :
CATEGORIES
PROJECTS
and between them another table which makes the link:
ASSIGNED_CAT with 2 columns: PROJECT_ID and CATEGORY_ID
In ASSIGNED_CAT I get the IDs of CATEGORIES and PROJECTS linked together.
Now I need to get the CATEGORIES which contains PROJECTS and if not don't show them.
Example:
If CATEGORY 1 have projects display the CATEGORY NAME and if not don't show.
Any idea to trick this? I've tried many SQL JOIN without success.
I guess you are missing the EXISTS clause.
The following query selects all categories, for which at least one row exists in the intersection table.
SELECT category_name
FROM categories c
WHERE EXISTS (
SELECT 1
FROM assigned_cat ac
WHERE ac.category_id = c.category_id
)
Related
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.
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'm running some SQL through phpmyadmin. I'm trying to do a query with 2 tables. The first xlsws_product has all the product info the second xlsws_category_assn contains two columns one with category id and the other with product id. The category names are in a third table but I don't need them for this.
What I am looking to do is select the rows from the product table that are in the categories with id 210, 218 and 370. This is what I tried so far:
SELECT *
FROM xlsws_product
JOIN xlsws_product_category_assn ON xlsws_product.id = xlsws_product_category_assn.product_id
WHERE
xlsws_product_category_assn.category_id = '210' OR '218' OR '370'`
The result for this gave me 24090 rows from a bunch of categories and there should only by a handful of rows in those categories. What's bizarre here is that there are 56474 rows in the product table so I'm not sure how the results are being filtered.
Just for the hell of it I tried limiting my query to just one category id with the following query:
SELECT *
FROM xlsws_product
JOIN xlsws_product_category_assn ON xlsws_product.id = xlsws_product_category_assn.product_id
WHERE xlsws_product_category_assn.category_id = '210'
This yielded zero rows...
I'm sure there is something simple I am missing but after spending a while searching for a solution I just can't figure it out. Thanks for the help.
If you need to find all the data which are in the category '210' OR '218' OR '370'
You can do as
SELECT * FROM
xlsws_product xp
JOIN xlsws_product_category_assn xpc ON xp.id = xpc.product_id
WHERE
xpc.category_id in (210,218,370)
If you need to find the products which have all the 3 given category you can do as
SELECT * FROM
xlsws_product xp
JOIN xlsws_product_category_assn xpc ON xp.id = xpc.product_id
WHERE
xpc.category_id in (210,218,370)
group by xp.id having count(*) = 3
I have a products catalog that is imported directly to a website's database. Each product row lists its Category and Subcategory. After the products are imported, I run this SQL to add the distinct categories to the database (which are used for creating navigation URLs based on their ids):
INSERT INTO categories (name) SELECT Distinct category FROM catalog_products;
Now, I want to add the subcategories as well to it's own table, but with a reference to the ID of it's parent Category, which is what I'm having trouble with.
Example: the product "SDH 20" belongs to the Category "Diagnose" (has an id 5 on the 'categories' table) and to the subcategory "Hematology". The 'subcategories' table will then have to list Hematology as having a categoryID of 5, which is the ID of "Diagnose" on the category table. Here is the SQL I've attempted:
INSERT INTO subcategories (name, idCategory) SELECT Distinct subcategory FROM catalog_products UNION ALL SELECT id from category WHERE categories.name = (SELECT catalog_products.category FROM catalog_products);
But I get a "#1242 - Subquery returns more than 1 row" error.
Is it possible to populate the 'subcategories' table's name and idCategory with one SQL that reads the catalog_products rows? If so, what is wrong with my SQL?
You have to use 'IN' if your subselect Returns more than one row:
INSERT INTO subcategories (name, idCategory)
SELECT Distinct subcategory FROM catalog_products
UNION ALL SELECT id from category WHERE
categories.name in (SELECT catalog_products.category FROM catalog_products);
^^
Came up with one possible answer to my own question.
This was somewhat of a confusing query because it was dealing with 3 different tables at the same time, so I tried splitting into two simpler SQLs.
First, just like the categories table, I added all the distinct subcategory name's without their parent categoryID field.
INSERT INTO subcategories (name) SELECT Distinct subcategory FROM catalog_products;
Now, I update the existing subcategories with the categoryID of their parent category with this SQL, that also target's the products catalog:
UPDATE subcategories SET idCategory = (SELECT categories.id FROM categories,catalog_products WHERE subcategories.name IN (Select catalog_products.subcategory) AND categories.name IN (Select catalog_products.category));
As i understood you have two tables:
CATEGORIES: id|name
CATALOG_PRODUCTS: product|category|subcategory
UNION ALL gives you two different rows instead of two values that you expect. Try this:
INSERT INTO subcategories (NAME, idCategory)
SELECT cp.subcategory, c.categoryID FROM catalog_products AS cp
JOIN categories AS c ON cp.category=c.name
GROUP BY cp.name
You just need to join both tables on name and if you want to DISTINCT use GROUP BY
Hope that helps. Have not tested this SQL so correct it a bit if needed
Apologies if this has been asked before but I really didn't know what to search and thus not sure how to word the question title so fingers crossed.
I'm building quite a common system where one product can have multiple categories and on the front-end, the user can search for products specifying multiple categories.
Say we had the following schema and data ( I cant post images yet, apologies, please see link )-
table name: product_categories
Data:
The products table is very standard - id, name, amount etc.
So product 1 has 2 categories.
If the user checks 2 tickboxes on the search page which represent category 2 and 3, how would I query that so only products which have both of those categories come back?
Something such as follows doesn't work, as there is no one row in that which has a category id of 2 AND a category id of 3:
SELECT * from product_categories where `category_id` = 2 AND `category_id` = 3;
I've tried using WHERE IN aswell, however, this would return product 1 even if i was looking for products which had both category id 2 and 6 ( for example ) which I don't want.
This is part of a bigger query however, I will be able to apply the solution if I manage to find one.
Something along this way should work
SELECT * FROM products WHERE
EXISTS (SELECT * FROM product_categories
WHERE product_id = products.id AND category_id = 2)
AND
EXISTS (SELECT * FROM product_categories
WHERE product_id = products.id AND category_id = 3)
...
Other solution is to generate JOIN for each category.
SELECT * FROM products
JOIN product_categories AS cs1 ON cs1.product_id = products.id
AND cs1.category_id = 2
JOIN product_categories AS cs2 ON cs2.product_id = products.id
AND cs2.category_id = 3
...
Unless you expect product_categories to be bigger than tens of millions of rows, both solutions should work reasonably, if correct indexes are created.
I think you need to use a sub-query here:
SELECT * from product_categories where id IN (SELECT id from product_categories where `category_id` = 2) AND IN (SELECT id from product_categories where `category_id` = 3)
I am not 100% sure this works (long time since I worked with SQL)
Many thanks for the suggestions guys, much appreciated. I think found a solution, this seems to produce the expected results but I'll be writing some more Unit Tests around my method to ensure it works.
The solution I found is as follows:
select * from products_categories where category_id in (2,3) HAVING count(distinct(id)) = 2
So this uses WHERE IN, however, using HAVING, it then checks the count of unique records returned and ensures it's equal to the amount of categories provided.
Cheers,
Darren