H2抱怨语法错误,MySQL接受它-但是,语法错误会给出正确的结果:Column ...必须在GROUP BY列表中;

问题描述

注意:已对问题进行了编辑,以包括表格并显示结果的确切含义。

可以说我们有一个sql表是由以下人员生成的:

CREATE TABLE T1 (
  `a` INTEGER,`b` DATETIME,`c` VARCHAR(5)
);

INSERT INTO T1
  (`a`,`b`,`c`)
VALUES
  ('5678','2008-01-01 12:00','12.34'),('5678','2008-01-01 12:01',NULL),'2008-01-01 12:02','2008-01-01 12:03','23.45'),'2008-01-01 12:04',NULL);

我需要执行的是

SELECT * FROM(
  SELECT a,b,c  from T1
)AS Q GROUP BY c ORDER BY a,b;

哪个给:

5678    2008-01-01 12:00:00     12.34
5678    2008-01-01 12:01:00     NULL
5678    2008-01-01 12:03:00     23.45

H2暗示(并接受)的是

SELECT * FROM(
  SELECT a,c  from T1
)AS Q GROUP BY a,c ORDER BY a,c;

哪个给

5678    2008-01-01 12:00:00     12.34
5678    2008-01-01 12:01:00     NULL
5678    2008-01-01 12:02:00     NULL
5678    2008-01-01 12:03:00     23.45
5678    2008-01-01 12:04:00     NULL

根据您的一些建议,这些是查询和结果。

建议1:

SELECT  max(a) as a,max(b) as b,c
FROM (
  SELECT a,c  from T1
) AS Q 
GROUP BY c 
ORDER BY a,b;

给予

5678    2008-01-01 12:00:00     12.34
5678    2008-01-01 12:03:00     23.45
5678    2008-01-01 12:04:00     NULL

建议2:

SELECT * 
FROM (
  SELECT a,c from T1
) AS Q 
GROUP BY c,a,b 
ORDER BY a,b;

给予

5678    2008-01-01 12:00:00     12.34
5678    2008-01-01 12:01:00     NULL
5678    2008-01-01 12:02:00     NULL
5678    2008-01-01 12:03:00     23.45
5678    2008-01-01 12:04:00     NULL

===============================

我需要获取一个查询执行的结果。

如何在获得所需结果的同时适当更改语法以适应H2需求?

解决方法

现在,针对修改后的问题。根据示例数据,在H2中可以执行以下操作:

select t1.*
from t1
join (
  select c,min(b) as min_b from t1 group by c
) x on t1.c is not distinct from x.c and t1.b = x.min_b
order by t1.b;

结果:

A     B                      C     
----  ---------------------  ------
5678  2008-01-01 12:00:00.0  12.34 
5678  2008-01-01 12:01:00.0  <null>
5678  2008-01-01 12:03:00.0  23.45 

用于重现案例的示例数据脚本为:

create table t1 (
  a integer,b datetime,c varchar(5)
);

insert into t1 (a,b,c) values
  ('5678',timestamp '2008-01-01 12:00:00','12.34'),('5678',timestamp '2008-01-01 12:01:00',null),timestamp '2008-01-01 12:02:00',timestamp '2008-01-01 12:03:00','23.45'),timestamp '2008-01-01 12:04:00',null);
,

H2行为正常。较旧版本的MySQL允许执行查询,即使根据ANSI / ISO SQL和几乎所有其他SQL实现(SQLite除外),查询仍然无效。

我在Reason for Column is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause

中写了一个解释它的示例

您必须更正查询才能使用H2。

规则是选择列表的每一列都必须在聚合函数内,或者必须在GROUP BY子句中命名。

您可以这样解决:

SELECT MAX(a) AS a,MAX(b) AS b,c FROM(
  SELECT a,c  from T1
)AS Q GROUP BY c ORDER BY a,b;

这符合规则,因为ab在聚合函数中,而cGROUP BY中。

MySQL 5.7和更高版本默认行为正确,并通过语义对组进行强制。

,

您可能正在使用用于接受此类查询的MySQL 5.7.5或更早版本。如果您使用的是更新的MySQL,则可能启用了旧的/格式错误的语法。

查询:

SELECT * 
FROM (
  SELECT a,c  from T1
) AS Q 
GROUP BY c 
ORDER BY a,b;

格式错误。为什么?因为必须将GROUP BY子句中未包括的列(在这种情况下为ab)汇总到选择列表中。您的选择列表包括所有列,自使用*以来没有任何列。

此格式错误的MySQL查询不符合SQL标准,并且会为非聚合列产生随机值。 这是您应用程序中的实际错误

但是,

H2会正确拒绝它,并要求您对其进行修复。您可以执行任何有效的替代选择,例如:

SELECT c,max(a) as a,max(b) as b
FROM (
  SELECT a,b;

或者也许:

SELECT * 
FROM (
  SELECT a,c from T1
) AS Q 
GROUP BY c,a,b 
ORDER BY a,b;
,

如果仅需要查询H2,则可以使用非标准PostgreSQL样式的DISTINCT ON子句来代替分组查询:

SELECT DISTINCT ON(C) A,B,C FROM T1 ORDER BY A,B;

AB的值将基于ORDER BY子句进行选择。