I have 2 tables on Debian server, rides and steps.
From a Xamarin app I get data from this server (Refit, Newtonsoft Json and SQLite-net PCL packages) to populate local tables.
When I use this query on mariadb:
SELECT 1_steps.*
FROM 1_rides, 1_steps
WHERE 1_rides.id=1_steps.ride_id
AND 1_rides.start=1
GROUP BY 1_rides.id
I got correct results (first step of each ride, then it starts with 1)
But when use equivalent for SqLite:
SELECT Steps.*
FROM Rides,Steps
WHERE Rides.Id=Steps.RideId
AND Rides.Start=1
GROUP BY Rides.Id
In the result, I get the last step of each (same) ride!
Whether on mariadb or sqlite, each table has a primary key (id
field).
I checked, the data is sent, received and saved in the same order.
Simply added in mobile app with:
foreach (var step in await App.RestClient.getSteps())
if (dbCon.InsertOrReplace(step) != 1)
....
I tried adding ORDER BY Rides.Id
but that does not change anything.
You are relying on something that is not allowed by strict SQL standards: whenever you have a group by
clause, the fields in the select
clause must either appear in the group by
clause as well, or must be aggregations (e.g. min
, count
), or must be functionally dependent on the group by
fields.
In your case those conditions are not met and so if the DB engine allows this, it will have to decide which value to pick within a same group: the first, the last, or still something else.
The way to deal with this, is to be explicit what you want to get in such a case, by specifying an aggregation:
SELECT 1_steps.id,
min(1_steps.step),
max(1_steps.whatever),
avg(1_steps.some_number),
...
FROM 1_rides
INNER JOIN 1_steps
ON 1_rides.id=1_steps.ride_id
WHERE 1_rides.start=1
GROUP BY 1_rides.id
You did not specify the fields of your table, but the idea should be clear: list the fields separately (not *
), and apply the type of aggregation to them you need.
If you are not interested in aggregating anything, but just want one particular record from steps
per ride, then don't use group by
, but specify the condition that filters exactly that one record from steps
:
SELECT 1_steps.*
FROM 1_rides
INNER JOIN 1_steps
ON 1_rides.id=1_steps.ride_id
WHERE 1_rides.start=1
AND 1_steps.step = 1
ORDER BY 1_rides.id
Note the condition 1_steps.step = 1
: you'll have to decide what that condition should be of course.