Mysql count left join strange result - mysql

Can someone help me to understand those results ? (For me all 3 should return 6455).
(Using RDS mysql-8.0.13)
SELECT COUNT(p.product_id) FROM product p LEFT JOIN product_attributes pa ON p.pdt_id = pa.pdt_id WHERE pa.code = 'season';
Results : 6332
SELECT COUNT(*) FROM product p;
Results : 6455
SELECT COUNT(p.product_id) FROM product p LEFT JOIN product_attributes pa ON p.pdt_id = pa.pdt_id AND pa.code = 'season';
Results : 6455

Your first join uses the WHERE clause, this mean sit selected all the rows, including those with a null join and then filters out those WHERE the pa.code = season, i.e. the null joins.
The last one joins on both, but because it is a left join you still get the full table of results, and nothing is filtered because you remove the WHERE clause. If you were to use an INNER JOIN in the last query you should get the same result (6332).
This link might be useful What's the difference between INNER JOIN, LEFT JOIN, RIGHT JOIN and FULL JOIN?

Related

What is the difference in mySQL AND vs Where

I'm using mysql and I confused with "And", "Where"
Somby dy can tell me what is difference between these.
SELECT *,COUNT(comment.id) as comment_count from posts LEFT JOIN comment on posts.post_id =comment.post_id AND comment.approve = 1 GROUP BY posts.post_id
SELECT *,COUNT(comment.id) as comment_count from posts LEFT JOIN comment on posts.post_id =comment.post_id WHERE comment.approve = 1 GROUP BY posts.post_id
They are not the same, first one will return the associations for all, and the second will do it just for the rows in the where match.
In this other duplicate question you can see the full explanation and examples
SQL JOIN - WHERE clause vs. ON clause
Simply change the query to use an inner join like this:
select tableA.id, tableA.name, tableB.details
from tableA
inner join tableB ...
here is the definition of left join:
The LEFT JOIN (also called LEFT OUTER JOIN) keyword returns all rows from the left table (table_name1), even if there are no matches in the right table (table_name2).
whereas the definition of the inner join is:
The INNER JOIN keyword return rows when there is at least one match in both tables.

why is inner join causing query to show only results with not null column?

I'm running the query below and it is working well.
SELECT
stock_parts.title,
COUNT(*) as qtyAvailable,
SUM(shipments.item_cost) as totalValue,
### stock_alerts.minimum
FROM
stock_items
INNER JOIN stock_parts ON stock_items.stock_part_id = stock_parts.id
INNER JOIN shipments ON shipments.id = stock_items.shipment_id
### INNER JOIN stock_alerts ON stock_alerts.stock_part_id = stock_items.stock_part_id
WHERE
stock_items.status IS NULL
AND stock_items.current_stock_id = 1
GROUP BY stock_parts.id
So if I uncomment the two commented lines (is a join to get info from another table), the query results are filtered showing only rows where stock_alerts.minimum is not null.
Why is this happening? I need all results event that column is NULL.
What INNER JOIN does is output the row results where none of the tables have null values on that cell. In other words (from W3 Schools):
The INNER JOIN keyword selects records that have matching values in
both tables
Try using FULL OUTER JOINinstead to get all the records even when one of the tables has a NULL value on it. See the explanation on W3 Schools FULL OUTER JOIN.
EDIT:
I didn't realize one of your tags is MySQL. Here you have a post that explains how to emulate a FULL OUTER JOIN in MySQL
Inner JOIN will ignore NULLS when you do an equal to comparison, I would suggest using IS DISTINCT FROM OPERATOR (<=>)
stock_alerts.stock_part_id <=> stock_items.stock_part_id

Subquery LIMIT causing issues when WHERE outside of subquery implemented

The subquery limits results perfectly when the WHERE clause at the end of the statement is not included. I understand that the subquery LIMIT happens first then the WHERE clause is fired on that result set and that this is a limitation/restriction of a subquery.
What I need is someone more experienced than me to help a brother out with retrieving the records with a LIMIT with the ability to restrict that result set by the WHERE clauses. Let me know if this was not explained well enough.
I also scoured the interwebs in search of the answer for hours with no luck. Your time is appreciated.
EDIT: added a crude example on SQLfiddle: http://sqlfiddle.com/#!9/2de563/4
SELECT *
FROM (SELECT * FROM parent_products LIMIT 10) pp
INNER JOIN products_variants pv ON pv.parent_id=pp.parent_id
INNER JOIN products p ON p.id=pv.product_id
INNER JOIN product_types pt ON pt.product_type_id=p.product_type
LEFT JOIN team_list t ON pp.team_id=t.team_id
LEFT JOIN photos ph ON ph.product_id=p.id
LEFT JOIN product_attributes pa ON pa.product_id=pv.product_id
LEFT JOIN attributes a ON a.id=pa.attribute_id
LEFT JOIN product_attribute_options po ON po.product_attribute_option_id=a.parent_id
WHERE t.team_id=100 AND p.active='y';
Explain select:
Below query will give you the expected output
SELECT * FROM (SELECT users.id,users.name FROM users
LEFT JOIN map ON users.id=map.user_id
LEFT JOIN locations ON locations.location_id=map.location_id
INNER JOIN type ON locations.type=type.id
WHERE type.id=1 limit 3) users
LEFT JOIN map ON users.id=map.user_id
LEFT JOIN locations ON locations.location_id=map.location_id
INNER JOIN type ON locations.type=type.id
where type.id=1;

Need to join MySql query to 3 tables

SELECT products.acctnum,products.subacctnum,NOW(),
items.amount,items.id,items.invoice_id,items.product_id,
items.po_id, invoices.customer_id, purchaseorders.vendor_id FROM items
INNER JOIN (products, invoices, purchaseorders)
ON (items.product_id=products.product_id AND items.invoice_id=invoices.id
AND items.po_id=purchaseorders.id)
This returns nothing... however..
SELECT products.acctnum,products.subacctnum,NOW(),
items.amount,items.id,items.invoice_id,items.product_id,
items.po_id, purchaseorders.vendor_id FROM items
INNER JOIN (products, purchaseorders)
ON (products.product_id=items.product_id AND purchaseorders.id=items.po_id)
Works...
SELECT products.acctnum,products.subacctnum,NOW(),
items.amount,items.id,items.invoice_id,items.product_id,
items.po_id, invoices.customer_id FROM items
INNER JOIN (products, invoices)
ON (products.product_id=items.product_id AND invoices.id=items.invoice_id)
Works...
Works for the rows I need in the result but when I join the 3rd table it doesn't work. LEFT JOIN displayed all the columns I needed but some rows were NULL.
I imagine the join clause you want looks more like this:
FROM items LEFT JOIN
invoices
ON invoices.id = items.invoice_id LEFT JOIN
purchaseorders
ON purchaseorders.id = items.po_id LEFT JOIN
products
ON products.product_id = items.product_id
I'm not sure which fields are not valid when you select them, but you can probably fix such issues by using coalesce() with appropriate fields from invoices and purchaseorders.

MySQL query: Slow response when joining table using ifnull

I have three tables, products, variants, and data.
Each product has it's own productcode. Products can have any number of variants including none. Variants have their own code variantcode. Products have a productid column, and each variant has a related productid column.
I want a list of all the codes, but I only care about the productcode if a product has no variants. Otherwise I want the variantcode. I wrote this query to get this list:
SELECT IFNULL(variants.variantcode, products.productcode) AS code
FROM products
LEFT OUTER JOIN variants ON (products.productid = variants.productid)
ORDER BY code
This query works as I expected.
The data table contains extra data for each code. I want to join this data onto this list. I tried this query:
SELECT IFNULL(variants.variantcode, products.productcode) AS code
FROM products
LEFT OUTER JOIN variants ON (products.productid = variants.productid)
LEFT OUTER JOIN data ON (data.partno = code)
ORDER BY code
But I get an error "Unknown column 'code' in 'on clause'". I assumed this had something to do with code being a generated value, so I then tried this query:
SELECT IFNULL(variants.variantcode, products.productcode) AS code
FROM products
LEFT OUTER JOIN variants ON (products.productid = variants.productid)
LEFT OUTER JOIN data ON (data.partno = IFNULL(variants.variantcode, products.productcode))
ORDER BY code
This query worked, but took a long time (~20 seconds vs <1 second for the first query). Is the IFNULL in the ON clause the problem? How can I speed it up?
Try this:
select product_variants.code from
(SELECT IFNULL(variants.variantcode, products.productcode) AS code
FROM products
LEFT OUTER JOIN variants ON (products.productid = variants.productid)
ORDER BY code)
as product_variants
LEFT OUTER JOIN data ON (data.partno = product_variants.code)
One thing you can try is to join to your data table twice, something like this:
SELECT IFNULL(variants.variantcode, products.productcode) AS code
, IFNULL(D1.something, D2.something) AS something
FROM products
LEFT OUTER JOIN variants
ON (products.productid = variants.productid)
LEFT OUTER JOIN data as D1
ON (D1.partno = variants.variantcode)
LEFT OUTER JOIN data as D2
ON (D2.partno = products.productcode)
ORDER BY code