I have one product table like this:
productid categoryid
and another category table like this:
categoryid parentid
would like to find rows missing from product table
select distinct c.parentid, pc.productid, from products_categories pc
join categories c on pc.categoryid = c.categoryid
where concat(pc.productid,'-',c.parentid) not in (
select distinct concat(productid,'-',categoryid) from products_categories
)
however this is extremely slow. is there a way to do this with joins instead of the not in concat line? the concat is used to account for all possible combos.
Everytime you are adding a prefix productID & - to either parentID or categoryID.
You can try this:
SELECT DISTINCT c.parentid, pc.productid
FROM products_categories pc
JOIN categories c on pc.categoryid = c.categoryid
WHERE c.parentid NOT IN (
SELECT DISTINCT categoryid FROM products_categories
)
Edit 1: doesnt account for all combos
SELECT DISTINCT c1.parentid, pc.productid
FROM products_categories pc
INNER JOIN categories c1 ON pc.categoryid = c1.categoryid
LEFT JOIN categories c2 ON c1.parentid = c2.categoryid
WHERE c2.categoryid IS NULL
To find what is in tbl_x but not in tbl_y, do this
SELECT ...
FROM tbl_x
LEFT JOIN tbl_y USING(...)
WHERE tbl_y.id IS NULL;
The construct IN ( SELECT ... ) is very poorly optimized. LEFT JOIN is well optimized (assuming suitable index).
Related
Let's say I'm having three tables as follows:
PRODUCT table (P) has ID, NAME
CATEGORY table (C) has ID, NAME
RELATION table (R) has ID, PRODUCT_ID, CATEGORY_ID
I'm currently on the product list page and I want a function to be able to search products by its category name.
select P.*
from P
where P.id in (select group_concat(distinct R.product_id) from C join R on C.id=R.category_id where C.name like '%something%')
The above SQL will only give me the first match, but running the query in the brackets will return more than one id. How do I correct this?
The group_concat() is unnecessary:
select P.*
from P
where P.id in (select R.product_id
from C join
R
on C.id = R.category_id
where C.name like '%something%'
);
Your query is fine, but it would more typically be written as:
select P.*
from P join
R
on P.id = R.product_id join
C
on C.id = R.category_id
where C.name like '%something%';
This version could return duplicates, if more than one category matched the like condition.
I have 2 tables:
Products ( 53k rows )
Product Categories ( 170k rows )
I'm trying to find uncategorized products with this query:
SELECT * FROM `jp_harley_products`
WHERE product_id NOT IN
(SELECT p_cat_product_id
FROM jp_harley_product_cats )
also tried this:
SELECT p.product_id,pc.p_cat_product_id
FROM `jp_harley_products` p
LEFT JOIN `jp_harley_product_cats` pc on pc.p_cat_product_id = p.product_id
My PHPmyAdmin can't handle this, as it doesn't show any results.
In harley_product_cats I have columns like: Product ID, Cat ID, so basically I want to get these products which doesn't have any relation in harley_product_cats
Can anyone help me with this?
You need to include a IS NULL for the LEFT JOIN one to work.
SELECT p.product_id, pc.p_cat_product_id
FROM `jp_harley_products` p
LEFT JOIN `jp_harley_product_cats` pc on pc.p_cat_product_id = p.product_id
WHERE p.product_id IS NULL
Or try using WHERE NOT EXISTS
SELECT p.product_id, pc.p_cat_product_id
FROM `jp_harley_products` p
WHERE NOT EXISTS (SELECT 1 FROM jp_harley_product_cats pc WHERE p.product_id = pc.p_cat_product_id );
Just when I thought I had figured out MySQL JoINS I run into this and it's doing my head in..
I've three tables for a shop:
tblProducts tblProdCat tblCategory
prodID prodCatID categoryID
prodName categoryID categoryHidden
prodPrice prodID categoryName
And what i'd like to do is create a query that finds products in a category that aren't hidden and I cannot get this to work.
At present all I can do is find the products in a category by joining the products table to the ProdCat table. As this query works I adapted it to this:
SELECT
p.prodID, p.name,
FROM
tblProducts p
INNER JOIN
tblProdCat pc
ON
pc.prodID = p.prodID
inner JOIN
tblCategory c
ON
c.categoryID = pc.categoryID
WHERE
pc.categoryID = '7' AND
c.categoryHidden = '0'
Can anybody help me identify why this isn't working?
edit: fixed the name of prodID (it was a typo and not what is causing the issue)
You do not have a column called productID on tblProducts
try
SELECT p.prodID, p.name,
FROM tblProducts p
INNER JOIN tblProdCat pc
ON pc.productID = p.prodID
inner JOIN tblCategory c
ON c.categoryID = pc.categoryID
WHERE pc.categoryID = '7' AND c.categoryHidden = '0'
Also I can not tell from your schema but if pc.categoryID is a number then you do not need quotes.
select * from tblProducts as p Inner join tblProdCat as pc Inner join tblCategory as c
where pc.categoryID = '7' AND c.categoryHidden = '0'
try this way
Try something like this (just dummy code )
select p.productID, p.name from
tblProducts as p,tblCategory as c,tblProdCat as pc
where pc.categoryID = '7' AND c.categoryHidden = '0'
I have a table called products and a table called product_description
They both have a column called product_id which is used to link them.
How do I get all the rows from the product_description table whose product_id is
not found in the products table?
I tried this:
SELECT *
FROM `product_description`
JOIN product ON product_description.product_id = product.product_id
WHERE product_description.product_id != product.product_id
But that returned zero rows.
Use a left outer join and find where there are no matches:
SELECT product_description.*
FROM `product_description` left outer join product
on product_description.product_id = product.product_id
where product.product_id is null
INNER JOIN filters out mismatches. That's why you don't get any results with your query. What you need is an OUTER JOIN
SELECT *
FROM product_description d LEFT JOIN product p
ON d.product_id = p.product_id
WHERE p.product_id IS NULL
or you can use a subquery with NOT IN
SELECT *
FROM product_description
WHERE product_id NOT IN
(
SELECT product_id
FROM product
)
or with NOT EXISTS
SELECT *
FROM product_description d
WHERE NOT EXISTS
(
SELECT *
FROM product
WHERE product_id = d.product_id
)
Here is SQLFiddle demo for all above-mentioned queries
To better understand JOINs see A Visual Explanation of SQL Joins
I have 3 MySQL tables.
companies with company_id and company_name
products with product_id and company_id
names with product_id, product_name and other info about the product
I'm trying to output the product_name and the company_name in one query for a given product_id.
Basically I need information from the names and companies tables and the link between them is the products table.
How do I do a join that needs to "bounce" off a third table?
Something like this but this obviously doesn't work:
SELECT product_name, company_name
FROM names
LEFT OUTER JOIN companies ON
(names.product_id = products.product_id and products.company_id = companies.company_id)
WHERE product_id = '12345'
select n.product_name, c.company_name
from names n
left outer join products p on n.product_id = p.product_id
left outer join companies c on p.company_id = c.company_id
where n.product_id = '12345'
You nearly have it, you just need to include the third table as another join in your query:
SELECT product_name, company_name
FROM names
LEFT JOIN products ON names.product_id = products.product_id
LEFT JOIN companies ON products.company_id = companies.company_id
WHERE product_id = '12345'
Also you should note that if you are using LEFT JOIN then the company name could be NULL if the company that made the product is unknown. So you need to test for that in your code to avoid an exception. If you know that it should never be NULL, or if you want to explicilty exclude products for which you don't know the company then use an INNER JOIN instead of a LEFT JOIN in both cases.