H2 抱怨错误的语法,MySQL 接受它 - 但是,错误的语法给出了正确的结果: Column ... must be in the GROUP BY list;
H2 complains about the bad grammar, MySQL accepts it - However, bad syntax gives the right results: Column ... must be in the GROUP BY list;
注意:对问题进行了编辑以包含表格并显示预期的结果。
假设我们有一个 SQL Table 生成者:
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),
('5678', '2008-01-01 12:02', NULL),
('5678', '2008-01-01 12:03', '23.45'),
('5678', '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, b, c from T1
)AS Q GROUP BY a,b,c ORDER BY a, b, 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, 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:03:00 23.45
5678 2008-01-01 12:04:00 NULL
建议2:
SELECT *
FROM (
SELECT a, b, 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 运行正常。 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。
规则是 select 列表的每一列都必须在聚合函数内或者在 GROUP BY 子句中命名。
你可以这样解决:
SELECT MAX(a) AS a, MAX(b) AS b, c FROM(
SELECT a, b, c from T1
)AS Q GROUP BY c ORDER BY a, b;
这满足规则,因为 a
和 b
在聚合函数中,而 c
在 GROUP BY
.
中
MySQL 5.7 及更高版本默认行为正确,按语义强制分组。
您可能使用的是 MySQL 5.7.5 或更早版本,它曾经接受过此类查询。如果您使用的是较新的 MySQL,您可能启用了 old/malformed 语法。
查询:
SELECT *
FROM (
SELECT a, b, c from T1
) AS Q
GROUP BY c
ORDER BY a, b;
格式错误。为什么?因为未包含在 GROUP BY
子句中的列(在本例中为 a
和 b
)必须聚合在 select 列表中。您的 select 列表包括所有列,并且 none 聚合自您使用 *
.
此格式错误的 MySQL 查询不符合 SQL 标准,并为 non-aggregated 列生成随机值。 这是您的应用程序的实际错误。
然而,H2 理所当然地拒绝它并要求您修复它。您可以执行任何有效的替代方法,例如:
SELECT c, max(a) as a, max(b) as b
FROM (
SELECT a, b, c from T1
) AS Q
GROUP BY c
ORDER BY a, b;
或者也许:
SELECT *
FROM (
SELECT a, b, c from T1
) AS Q
GROUP BY c, a, b
ORDER BY a, b;
如果您只需要查询 H2,可以使用 non-standard PostgreSQL-style DISTINCT ON
子句代替分组查询:
SELECT DISTINCT ON(C) A, B, C FROM T1 ORDER BY A, B;
A
和 B
值将根据 ORDER BY
子句选择。
现在,对于修改后的问题。根据示例数据,在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),
('5678', timestamp '2008-01-01 12:02:00', null),
('5678', timestamp '2008-01-01 12:03:00', '23.45'),
('5678', timestamp '2008-01-01 12:04:00', null);
注意:对问题进行了编辑以包含表格并显示预期的结果。
假设我们有一个 SQL Table 生成者:
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),
('5678', '2008-01-01 12:02', NULL),
('5678', '2008-01-01 12:03', '23.45'),
('5678', '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, b, c from T1
)AS Q GROUP BY a,b,c ORDER BY a, b, 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, 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:03:00 23.45
5678 2008-01-01 12:04:00 NULL
建议2:
SELECT *
FROM (
SELECT a, b, 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 运行正常。 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。
规则是 select 列表的每一列都必须在聚合函数内或者在 GROUP BY 子句中命名。
你可以这样解决:
SELECT MAX(a) AS a, MAX(b) AS b, c FROM(
SELECT a, b, c from T1
)AS Q GROUP BY c ORDER BY a, b;
这满足规则,因为 a
和 b
在聚合函数中,而 c
在 GROUP BY
.
MySQL 5.7 及更高版本默认行为正确,按语义强制分组。
您可能使用的是 MySQL 5.7.5 或更早版本,它曾经接受过此类查询。如果您使用的是较新的 MySQL,您可能启用了 old/malformed 语法。
查询:
SELECT *
FROM (
SELECT a, b, c from T1
) AS Q
GROUP BY c
ORDER BY a, b;
格式错误。为什么?因为未包含在 GROUP BY
子句中的列(在本例中为 a
和 b
)必须聚合在 select 列表中。您的 select 列表包括所有列,并且 none 聚合自您使用 *
.
此格式错误的 MySQL 查询不符合 SQL 标准,并为 non-aggregated 列生成随机值。 这是您的应用程序的实际错误。
然而,H2 理所当然地拒绝它并要求您修复它。您可以执行任何有效的替代方法,例如:
SELECT c, max(a) as a, max(b) as b
FROM (
SELECT a, b, c from T1
) AS Q
GROUP BY c
ORDER BY a, b;
或者也许:
SELECT *
FROM (
SELECT a, b, c from T1
) AS Q
GROUP BY c, a, b
ORDER BY a, b;
如果您只需要查询 H2,可以使用 non-standard PostgreSQL-style DISTINCT ON
子句代替分组查询:
SELECT DISTINCT ON(C) A, B, C FROM T1 ORDER BY A, B;
A
和 B
值将根据 ORDER BY
子句选择。
现在,对于修改后的问题。根据示例数据,在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),
('5678', timestamp '2008-01-01 12:02:00', null),
('5678', timestamp '2008-01-01 12:03:00', '23.45'),
('5678', timestamp '2008-01-01 12:04:00', null);