我在Debian服务器上有2个表,游乐设施和步骤。
从Xamarin应用程序中,我从此服务器(Refit,Newtonsoft Json和SQLite-net PCL包)获取数据以填充本地表。
当我在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
我得到了正确的结果(每次骑行的第一步步骤,然后从1开始)
但是当使用等效的SqLite时:
SELECT Steps.*
FROM Rides,Steps
WHERE Rides.Id=Steps.RideId
AND Rides.Start=1
GROUP BY Rides.Id
在结果中,我得到每个(相同)骑行的最后步骤!
无论是在mariadb还是sqlite上,每个表都有一个主键(id
字段)。
我检查过,数据以相同的顺序发送,接收和保存。
只需在移动应用中添加:
foreach (var step in await App.RestClient.getSteps())
if (dbCon.InsertOrReplace(step) != 1)
....
我尝试添加ORDER BY Rides.Id
,但这并没有改变任何内容。
答案 0 :(得分:1)
您依赖严格的SQL标准不允许的内容:只要您有group by
子句,select
子句中的字段必须出现在group by
子句中好吧,或者必须是聚合(例如min
,count
),或者必须在功能上依赖于group by
字段。
在你的情况下,这些条件不符合,所以如果数据库引擎允许这样做,它将必须决定在同一组中选择哪个值:第一个,最后一个,或者还有别的。
处理这个问题的方法是通过指定聚合来明确你想要得到的东西:
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
您没有指定表格的字段,但想法应该是明确的:单独列出字段(不是*
),并将聚合类型应用于您需要的字段。
如果您对聚合任何内容不感兴趣,但只想从每次steps
获得一条特定记录,那么请不要使用group by
,而是指定从{{1}完全过滤掉一条记录的条件{1}}:
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
:当然,您必须决定该条件应该是什么。