【问题标题】:SQLite Group By results order behaviour change 3.28.0 onwardsSQLite Group By 结果顺序行为更改 3.28.0 起
【发布时间】:2020-12-30 19:09:21
【问题描述】:

我注意到使用“GROUP BY”的结果顺序存在问题,而更高版本的 SQLite 正在努力解决。当 Android 11 使用 SQLite 3.28.0 时,我第一次注意到它。我现在将其归结为 SQLite 本身的行为变化。 问题是结果的顺序会根据版本而改变。我不确定这是我的错误或预期行为还是错误(尽管该错误在旧 SQLite 版本中已经正常工作了 8 年)。

示例表:

id|year|command |code
1 |2005|TV      |A
2 |2005|TV-CD   |B
3 |2005|CD      |B
4 |2010|TV      |B
5 |2015|TV      |C

如果我运行以下命令

SELECT * FROM myTable  GROUP BY command ORDER BY _id

在 SQLite 3.22 (Android 10) 或 3.23.1 中我得到:

2|2005|TV-CD|B
3|2005|CD   |B
5|2015|TV   |C

这是我想要的……

如果我在 SQLite 3.28 (Android 11) 或更高版本中运行相同的命令,我会得到

1|2005|TV   |A
2|2005|TV-CD|B
3|2005|CD   |B

如果您想自己尝试一下,这里有一个简单的表格示例

CREATE TABLE 'myTable' ('_id' integer PRIMARY KEY  ,'year' NUMERIC ,'command' TEXT, 'code' TEXT);
INSERT INTO myTable VALUES ("1","2005","TV","A");
INSERT INTO myTable VALUES ("2","2005","TV-CD","B");
INSERT INTO myTable VALUES ("3","2005","CD","B");
INSERT INTO myTable VALUES ("4","2010","TV","B");
INSERT INTO myTable VALUES ("5","2015","TV","C");
SELECT * FROM myTable  GROUP BY command ORDER BY _id

https://www.jdoodle.com/execute-sql-online/ 对测试很有用,因为它允许您即时更改 SQLite 版本。

【问题讨论】:

  • 您是按命令分组的,因此其他值不应该是相关的,除非它是聚合(如计数、平均值、总和等,但您没有使用任何值)
  • 您不应使用如下代码:SELECT * FROM myTable GROUP BY 命令。 SQLite 允许它(尽管其他数据库不允许)。但这没有意义。此类查询的结果是不可预测的。所以没有正确或错误的结果。你必须重新考虑你想要的结果。
  • 您可以使用max 聚合来获取最后一个ID。但对于其他值,您必须使用子查询/cte

标签: android sqlite android-sqlite


【解决方案1】:

正如我在评论中已经提到的,查询的结果如下:

SELECT * FROM myTable  GROUP BY command

是不可预测的,因为GROUP BY 应该只用于聚合,类似于:

SELECT command, MAX(year) AS max_year 
FROM myTable  
GROUP BY command

这将返回每个command 的最大year

因此,如果 GROUP BYSELECT * ... 的行为在较新版本中发生了变化,如果您不使用此类查询,则应该不是问题。

根据我在您的问题中读到的内容,您期望每个command 的结果中具有最大id 的行。

在标准 sql 和没有窗口函数的情况下,大多数版本的 android SQLite 仍然不支持,您可以先聚合,然后加入表。

但是,SQLite 有一个 documented feature 可供使用,以便您可以使用 bare 列。
这是有效的:

SELECT MAX(_id) AS _id, year, command, code
FROM myTable  
GROUP BY command
ORDER BY _id

对于每个 command,您将获得最大 _id 的行。

【讨论】:

  • 这个裸列功能是一个不错的发现!但这看起来也是一个很好的出错机会(例如,如果有多个最小值/最大值,则会出现歧义)
  • @njzk2 不,这是有据可查的。这仅在只有 MIN 或只有 MAX 时才有效。在任何其他情况下,结果都是不可预测的。
  • 这就是我要说的。这是一个非常有趣的功能,但如果将来有人在不了解该特定功能的情况下修改该查询,则很容易导致错误或误解。
【解决方案2】:

我找到了一个解决方案,并且可以确认它在两个版本的 SQLite 中都有效

SELECT _id,MAX (year),command,code FROM myTable  GROUP BY command  ORDER BY _id

【讨论】:

    猜你喜欢
    • 2011-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-01
    相关资源
    最近更新 更多