Die hele where kan inderdaad in de ON worden opgenomen. Door de where clausible op de juiste plaatsen in de join op te nemen beperkt je de resultaten welke moeten worden samengevoegd.
Als die subquery beduidend langer duurt, moet je die dus zien te optimaliseren.
Hoe lang duurt deze query bij jouw:
code:
1
2
3
| SELECT COUNT(L1.Phonenumber) as rownumber, L1.Phonenumber, L1.GMTDate
FROM Locations L1 inner join Locations L2 on L1.Phonenumber = L2.Phonenumber
AND L1.GMTDate <= L2.GMTDate GROUP BY L1.Phonenumber,L1.GMTDate having rownumber <= $rownumber |
Mocht je een foutmelding krijgen op having gebruik dan having count(L1.Phonenumber) <= $rownumber.
In deze query zitten twee optimalisaties. De eerste geeft explicit aan op veld veld je de count wilt uitvoeren ipv op alle velden (*). De tweede optimalisaties is de (inner) join constructie.
Je volledige query zou dan worden: (Nog een optimalisatie is alle velden van loc explicit vermelden zodat mysql niet eerst een lookup hoeft te doen in de systeemtabellen)
code:
1
2
3
4
5
6
7
8
9
| SELECT loc.* FROM Locations loc inner join
(
SELECT COUNT(L1.Phonenumber) as rownumber, L1.Phonenumber,L1.GMTDate
FROM Locations L1 inner join Locations L2 on L1.Phonenumber = L2.Phonenumber
AND L1.GMTDate <= L2.GMTDate GROUP BY L1.Phonenumber,L1.GMTDate
having rownumber <= $rownumber)
rownum on loc.Phonenumber = rownum.Phonenumber AND loc.GMTDate = rownum.GMTDate
inner join Devices on loc.Phonenumber = Devices.Phonenumber
and Devices.UserID = (select UserID from Users where Users.Username = '$user' ) |
Ik heb Users.Username uit de select weggelaten omdat je deze in de where explicit zetten (Users.Username='$user'). Die weet je dus al bij het uitvoeren van de query en hoef je dus niet nog een keer op te vragen. Als je UserID al weet, laat dan ook de subquery welke userid ophaalt hier achterwege en gebruik dan direct Devices.UserID=$userid.
If it isn't broken, fix it until it is..