You must put GROUP BY
before ORDER BY
. Take a look at SOQL SELECT Syntax:
SELECT fieldList [subquery][...]
[TYPEOF typeOfField whenExpression[...] elseExpression END][...]
FROM objectType[,...]
[USING SCOPE filterScope]
[WHERE conditionExpression]
[WITH [DATA CATEGORY] filteringExpression]
[GROUP BY {fieldGroupByList|ROLLUP (fieldSubtotalGroupByList)|CUBE (fieldSubtotalGroupByList)}
[HAVING havingConditionExpression] ]
[ORDER BY fieldOrderByList {ASC|DESC} [NULLS {FIRST|LAST}] ]
[LIMIT numberOfRowsToReturn]
[OFFSET numberOfRowsToSkip]
[FOR {VIEW | REFERENCE}[,...] ]
[ UPDATE {TRACKING|VIEWSTAT}[,...] ]
Also note that you must group all fields you query for. Correct syntax:
SELECT UserId, Status
FROM LoginHistory
WHERE UserId IN :userIds
GROUP BY UserId, Status
ORDER BY LoginTime DESC
If you want to get the most recent LoginHistory.Status
for each specified user, I don't think aggregates will help. Normally query row limits aren't a huge concern, so you can probably just pull in the last 30 days or some such and post-process them.
Map<Id, String> mostRecentStatus = new Map<Id, String>();
for (LoginHistory history : [
SELECT Status, UserId
FROM LoginHistory
WHERE Id IN :userIds
AND LoginTime >= LAST_N_DAYS:30
ORDER BY LoginTime, UserId DESC
]){
if (!mostRecentStatus.containsKey(history.UserId))
mostRecentStatus.put(history.UserId, history.Status);
}