1

我有一个按城市分组的表,侧列用于唯一条目,我需要查询每个城市的最新条目,侧组。(较新的条目总是具有较高的时间戳值)

在 SQLite 中,我可以使用 GROUP BY 来完成这项工作:http ://sqlfiddle.com/#!5/6c1c4/1/0

但在 MySQL 中,它不能以这种方式工作:http ://sqlfiddle.com/#!9/9ead9/1/0

我想我在这里误用/滥用了 GROUP BY,但是我怎样才能为 MySQL 和 SQLite 提供正确的语句?

4

2 回答 2

2

在您的示例中,MySQL 和 SQLite 都违反了 SQL 标准。

在标准 SQL(所有主要 SQL 引擎都支持)中,如果您使用GROUP BYinSELECT语句,则列表中允许的唯一表达式是 中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 用于 MySQLSQLFiddle 用于 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

它为MySQLSQLite生成相同的结果。(只有一个问题:它假设每个组的时间戳都是唯一的)。

于 2013-07-20T22:35:23.747 回答
1

在没有任何聚合函数的情况下(我在这里专门讨论 MySQL),使用 GROUP BY 子句是不合适且毫无意义的。也许您打算使用 DISTINCT 运算符。

于 2013-07-20T06:40:14.690 回答