Reputation: 993
I need to limit a join in a mysql query, I have the code below that I am using;
select customer.`name`, customer.`retainer_value`, updates.`date`
from updates
left join customer on customer.id = updates.`clientid`
WHERE customer.`retainer_value` < 250
AND customer.switchedoff = 'N'
AND customer.companyid <> 3
AND customer.retainer_value > 20
group by updates.clientid
order by updates.date DESC
I am trying to select all of the customers from the customers table that meet the where criteria and left join the latest update in the updates table for that customer.
Is there an easy way to do this or do I need to do it via PHP?
Upvotes: 0
Views: 112
Reputation: 69829
You have fallen into the trap of the MySQL GROUP BY extension. Just because you have put ORDER BY Date DESC
it does not mean that the date returned will be the latest.
The MySQL documents state:
MySQL extends the use of GROUP BY so that the select list can refer to nonaggregated columns not named in the GROUP BY clause
But it also goes on to say:
The server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate. Furthermore, the selection of values from each group cannot be influenced by adding an ORDER BY clause.
It is for this reason that I always advise to avoid the impicit grouping that MySQL offers as it can very easily lead to non determistic queries.
So all your ORDER BY
clause is doing is once any date has been retrived for each client, it orders the final result set in order of the date picked. If you want the latest update date, the only way to do this deterministically is to use the MAX
function:
select customer.`name`, customer.`retainer_value`, MAX(updates.`date`) as Date
from updates
inner join customer on customer.id = updates.`clientid`
WHERE customer.`retainer_value` < 250
AND customer.switchedoff = 'N'
AND customer.companyid <> 3
AND customer.retainer_value > 20
group by updates.clientid, customer.`name`, customer.`retainer_value`;
N.B I have changed your left join to an inner join as your where clause had effectively done this anyway. If you want customers with no updates then you would need to change your clause to select from customers, then left join to updates
Upvotes: 1
Reputation: 1271231
First, you need to do the left join
in the right order, if you want to keep all customers that meet the filter. This means that the customer
table should be first in the left join
.
Then, if you jut want the most recent date, then use max()
:
select c.`name`, c.`retainer_value`, max(u.`date`)
from customer c left join
updates u
on c.id = u.`clientid`
WHERE c.`retainer_value` < 250 AND c.switchedoff = 'N' AND c.companyid <> 3 AND
c.retainer_value > 20
group by c.id
order by max(u.`date`) DESC
Upvotes: 1