sqlite GROUP BY语句中的奇迹

时间:2013-07-20 06:33:26

标签: mysql sqlite group-by

我有一个按城市,侧栏分组的表格,用于输入唯一条目,我需要查询每个城市,边路组的最新条目。 (较新的条目始终具有较高的时间戳值)

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

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

我认为我在这里滥用/滥用GROUP BY,但我怎么能有MySQL和SQLite的正确陈述?

2 个答案:

答案 0 :(得分:2)

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

在标准SQL中(由所有主要SQL引擎支持),如果在GROUP BY语句中使用SELECT,则SELECT列表中允许的唯一表达式是GROUP BY中列出的列1}},或聚合函数调用(如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 for MySQLSQLFiddle for 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生成相同的结果。 (只有一个问题:它假定每个组的时间戳是唯一的。)

答案 1 :(得分:1)

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