Using GROUP BY and HAVING on a LEFT JOIN table where there is no records stored

KDJ :

There is a table where payment data towards invoices are recorded. I am using SUM to count the total payment amount towards the invoice. I only want to show invoices that have not been paid. So I created a WHERE clause using GROUP BY and HAVING to only show records that have records sum'ing to less than the total invoice amount.

But...If there are no records to find in the Payments table, the system cannot find any invoices to display. Anyone else had this issue? I'm open to changing to a different format but I need it to function the same way where it only finds invoices with payment amounts of less than the total invoice amount due OR no payments at all.

$query = "
SELECT o.id, o.user_id,o.invoice_number,o.total,SUM(p.payment_amount) as paid 
FROM User_Order_Details as o 
LEFT JOIN User_Payments as p ON (p.user_id = o.user_id AND p.order_id = o.id) 
WHERE o.user_id = '1' AND o.invoice_number != '' 
GROUP BY p.order_id 
HAVING SUM(p.payment_amount) < o.total 
ORDER BY o.ship_date DESC
");
Nick :

Your issue is that when no payments have been made, SUM(p.payment_amount) is NULL, and comparing NULL to anything always results in FALSE (hence HAVING SUM(p.payment_amount) < o.total doesn't return those rows). So you need to use COALESCE to convert that value into 0, which can then be successfully compared. Note that MySQL allows you to use aliases in the HAVING clause, so you can just use paid there:

$query = "
SELECT o.id, o.user_id,o.invoice_number,o.total, COALESCE(SUM(p.payment_amount),0) as paid 
FROM User_Order_Details as o 
LEFT JOIN User_Payments as p ON (p.user_id = o.user_id AND p.order_id = o.id) 
WHERE o.user_id = '1' AND o.invoice_number != '' 
GROUP BY p.order_id 
HAVING paid < o.total 
ORDER BY o.ship_date DESC
");

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=386345&siteId=1