我有一个按城市分组的表,侧列用于唯一条目,我需要查询每个城市的最新条目,侧组。(较新的条目总是具有较高的时间戳值)
在 SQLite 中,我可以使用 GROUP BY 来完成这项工作:http ://sqlfiddle.com/#!5/6c1c4/1/0
但在 MySQL 中,它不能以这种方式工作:http ://sqlfiddle.com/#!9/9ead9/1/0
我想我在这里误用/滥用了 GROUP BY,但是我怎样才能为 MySQL 和 SQLite 提供正确的语句?
我有一个按城市分组的表,侧列用于唯一条目,我需要查询每个城市的最新条目,侧组。(较新的条目总是具有较高的时间戳值)
在 SQLite 中,我可以使用 GROUP BY 来完成这项工作:http ://sqlfiddle.com/#!5/6c1c4/1/0
但在 MySQL 中,它不能以这种方式工作:http ://sqlfiddle.com/#!9/9ead9/1/0
我想我在这里误用/滥用了 GROUP BY,但是我怎样才能为 MySQL 和 SQLite 提供正确的语句?
在您的示例中,MySQL 和 SQLite 都违反了 SQL 标准。
在标准 SQL(所有主要 SQL 引擎都支持)中,如果您使用GROUP BY
inSELECT
语句,则列表中允许的唯一表达式是 中SELECT
列出的列GROUP BY
,或对任何其他列的聚合函数调用(如count()
、sum()
、avg()
等)。
大多数 SQL 引擎:PostgreSQL、Oracle、MSSQL、DB2 都严格遵循这条规则——它们不允许任何其他语法。
然而,MySQL 和 SQLite 都决定在这方面更加宽松,我认为这是一个很大的错误,也是造成混乱的无穷无尽的根源。虽然它似乎有效,但绝对不清楚到底发生了什么。例如,查询生成的 SQLite 时间戳列与原始表源中存在的任何内容都不同。
如果你不想有任何惊喜,你应该遵循标准。在您的情况下,这意味着使用如下语句:
SELECT
min(period),
side,
city,
min(gold),
min(silver),
min(normal),
min(timestamp)
FROM cities
GROUP BY city, side
ORDER BY min(timestamp)
当您使用它时,MySQL 和 SQLite(以及与此相关的任何其他数据库)都返回相同的结果:SQLFiddle 用于 MySQL,SQLFiddle 用于 SQLite。
更新:此语句将在符合标准的 SQL 中执行您想要的操作:
SELECT
c.period,
g.side,
g.city,
c.gold,
c.silver,
c.normal,
g.timestamp
FROM cities c,
(SELECT
side,
city,
max(timestamp) AS timestamp
FROM cities
GROUP BY city, side) g
WHERE c.side = g.side
AND c.city = g.city
AND c.timestamp = g.timestamp
ORDER BY c.timestamp
在没有任何聚合函数的情况下(我在这里专门讨论 MySQL),使用 GROUP BY 子句是不合适且毫无意义的。也许您打算使用 DISTINCT 运算符。