SqLite 和 MariaDb 之间的结果不同 SELECT
Not the same result between SqLite and MariaDb SELECT
我在 Debian 服务器上有 2 tables,游乐设施和步骤。
从 Xamarin 应用程序中,我从该服务器(Refit, Newtonsoft Json and SQLite-net PCL 包)获取数据以填充本地 tables。
当我在 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上,每个table都有一个主键(id
字段)。
我查了一下,数据是按照同样的顺序发送、接收和保存的。
只需在移动应用中添加:
foreach (var step in await App.RestClient.getSteps())
if (dbCon.InsertOrReplace(step) != 1)
....
我尝试添加 ORDER BY Rides.Id
但这并没有改变任何东西。
您所依赖的东西是严格的 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
您没有指定 table 的字段,但思路应该很清楚:单独列出字段(而不是 *
),然后将聚合类型应用于您需要的字段。
备选
如果您对汇总任何内容不感兴趣,而只想每次骑行 steps
中的一条特定记录,则不要使用 group by
,但要指定准确过滤该条记录的条件来自 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
注意条件1_steps.step = 1
:您当然必须决定该条件应该是什么。
我在 Debian 服务器上有 2 tables,游乐设施和步骤。
从 Xamarin 应用程序中,我从该服务器(Refit, Newtonsoft Json and SQLite-net PCL 包)获取数据以填充本地 tables。
当我在 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上,每个table都有一个主键(id
字段)。
我查了一下,数据是按照同样的顺序发送、接收和保存的。
只需在移动应用中添加:
foreach (var step in await App.RestClient.getSteps())
if (dbCon.InsertOrReplace(step) != 1)
....
我尝试添加 ORDER BY Rides.Id
但这并没有改变任何东西。
您所依赖的东西是严格的 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
您没有指定 table 的字段,但思路应该很清楚:单独列出字段(而不是 *
),然后将聚合类型应用于您需要的字段。
备选
如果您对汇总任何内容不感兴趣,而只想每次骑行 steps
中的一条特定记录,则不要使用 group by
,但要指定准确过滤该条记录的条件来自 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
注意条件1_steps.step = 1
:您当然必须决定该条件应该是什么。