Mysql query group by to be combined with order by desc
Domanda
I have the following query as below.
SELECT Day(vehicleTrip.startDateTime) As day,
Month(vehicleTrip.startDateTime) As month,
Sum(TIMESTAMPDIFF(SECOND, startDateTime, endDateTime )) As totalDuration,
count(vehicleTrip.startDateTime) As totalTrip,
sum(endMileage-startMileage) As totalMleage
FROM vehicleTrip
WHERE vehicleTrip.vehicleID=:vehicleID
AND vehicleTrip.vehicleEndCodeID!=1
AND vehicleTrip.startDateTime BETWEEN :startDateTime And :endDateTime
Group By Day(vehicleTrip.startDateTime),Month(vehicleTrip.startDateTime)
Currently it works fine cause it can group by the daily date the sum of duration, totalTrip, totalMileage etc.
But only issue I want the date to be arrange by desc. I have tried putting the order by startDateTime desc it gives me error that its not in GROUP By clause and containts nonaggregated column
. I have tried many method like even putting the Max(vehicleTrip.startDateTime)
still the same. How best can I resolve this ?
Below is my table design with its index.
CREATE TABLE `vehicleTrip` (
`vehicleEndCodeID` tinyint NOT NULL DEFAULT '1',
`vehicleID` mediumint NOT NULL,
`startDateTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`endDateTime` timestamp NULL DEFAULT NULL,
`startMileage` float(11,3) DEFAULT NULL,
`endMileage` float(11,3) DEFAULT NULL,
`startLatitude` float(10,8) NOT NULL,
`startLongitude` float(11,8) NOT NULL,
`endLatitude` float(10,8) DEFAULT NULL,
`endLongitude` float(11,8) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `vehicleTrip`
ADD PRIMARY KEY (`vehicleID`,`startDateTime`) USING BTREE;
COMMIT;
Soluzione
Perhaps this is what you are looking for?
SELECT Day(startDateTime) As "day",
Month(startDateTime) As "month",
Sum(TIMESTAMPDIFF(SECOND, startDateTime, endDateTime ))
As totalDuration,
count(*) As trips,
sum(endMileage-startMileage) As totalMleage
FROM vehicleTrip
WHERE vehicleID = :vehicleID
AND vehicleEndCodeID != 1
AND startDateTime BETWEEN :startDateTime And :endDateTime
Group By 2, 1
ORDER BY 2 DESC, 1 DESC
(I'm assuming you want to sort by both month and day, latest first?)
Also consider
GROUP BY DATE(startDateTime)
ORDER BY DATE(startDateTime) DESC
More
!=
is hard to optimize. I don't see any way to avoid the 'filesort', but this index might help with performance:
INDEX(vehicleID, startDateTime) -- in this order
However, since that is already the PRIMARY KEY
, do not add this INDEX
.
Starting over
Now that the CREATE TABLE
has been added (and this is why I ask for such so often), here is how I would answer the question:
When possible, have the same ORDER BY
as GROUP BY
. This allows the Optimizer to both at the same time. In your question, you did not quite have the same stuff in each.
A variation on such is to change the direction:
GROUP BY a , b
ORDER BY a DESC, b DESC
is also optimal.
(Not relevant here:) In most cases, any mixture of ASC and DESC on the columns in ORDER BY
prevents any optimization of the ORDER BY
.
My suggestion of using DATE(..)
instead of the two columns avoids the issue and solves the potential bug that will show up next January. BUT... It may run into the "only full group by" issues since DAY(..), MONTH(..)
is not recognized as a subset of `DATE(..)
To avoid some of the above mess, I started by suggesting
GROUP BY 2 , 1
ORDER BY 2 DESC, 1 DESC
If this fails, I will pull a subquery out of my sleeve.