始终使用group by
。
我在使用MariaDB中的select
,having
和order by
的{{1}}查询时遇到问题:
limit
假设我们有两行简单的mysql Ver 15.1 Distrib 10.1.9-MariaDB, for Linux (x86_64) using readline 5.1
表:
test
我们还有一个简单的代理函数DROP TABLE IF EXISTS `test`;
CREATE TABLE `test` (
`weight` INT(11) NOT NULL,
`x` INT(11) NOT NULL
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
INSERT INTO `test` (`weight`, `x`) VALUES (1, 33);
INSERT INTO `test` (`weight`, `x`) VALUES (1, 44);
,它只通过第一个参数:
TestProxy
DROP FUNCTION IF EXISTS `TestProxy`;
delimiter //
CREATE FUNCTION `TestProxy`(
x double(9,6)
) RETURNS double(8,2)
NO SQL
BEGIN
RETURN x;
END//
delimiter ;
如果我使用where
条件运行以下选择查询,我希望得到一个行:
where
SELECT
`test`.weight,
`test`.x
FROM `test`
WHERE 35 <= TestProxy(`test`.x)
ORDER BY weight ASC
LIMIT 0, 1;
但是,如果我将having
替换为where
,我会在MariaDB中设置空。在MySQL中,我期望得到一个行:
having
SELECT
`test`.weight,
`test`.x
FROM `test`
HAVING 35 <= TestProxy(`test`.x)
ORDER BY weight ASC
LIMIT 0, 1;
但没有having
函数的工作查询此外,当我使用TestProxy
并再次将having
替换为TestProxy
时,我希望得到一个行:
test.x
SELECT
`test`.weight,
`test`.x
FROM `test`
HAVING 35 <= `test`.x
ORDER BY weight ASC
LIMIT 0, 1;
进行查询但使用having
最后,当我使用select
打包查询并将select
移到包装器时,我希望得到一行行:
limit
但是,这个查询非常慢。
SELECT * FROM (
SELECT
`test`.weight,
`test`.x
FROM `test`
HAVING 35 <= TestProxy(`test`.x)
ORDER BY weight ASC
) as table1
LIMIT 0, 1;
进行查询,具体取决于having
在阅读并分析了@slaakso和@ gordon-linoff的答案之后,我进一步调查了它,简化了问题,并意识到只有在第一次出现在将返回的结果集上时才会返回一行在应用order by
之前。
因此,一个行会产生以下查询:
limit
以下查询将以空设置:
SELECT
33 = TestProxy(`test`.x) as tp
FROM `test`
HAVING tp
ORDER BY x ASC
LIMIT 0, 1;
SELECT
33 = TestProxy(`test`.x) as tp
FROM `test`
HAVING tp
ORDER BY x DESC
LIMIT 0, 1;
和having
如果我添加group by
,则在MariaDB中按预期方式返回一个行:
group by
有人可以解释为什么MariaDB存在不一致之处?我错过了什么,或者是MariaDB中的错误? 我想这与优化查询有关,但我不知道如何检查它。
有没有人建议如何修复它?这显然是一个简化的例子;我的复杂查询需要 SELECT
33 = TestProxy(`test`.x) as tp
FROM `test`
GROUP BY tp
HAVING tp
ORDER BY x DESC
LIMIT 0, 1;
。
答案 0 :(得分:1)
一种可能性非常微妙。这是&#34;工作的查询&#34;在MySQL但没有&#34;#34;工作&#34;在MariaDB:
SELECT `test`.weight, `test`.x
FROM `test`
HAVING 35 <= TestProxy(`test`.x)
ORDER BY weight ASC
LIMIT 0, 1;
我怀疑使用不在select
列表中的表达式,以及没有having
的{{1}}。
documentation明确指出:
标准SQL的另一个MySQL扩展允许引用 选择列表中的别名表达式的HAVING子句。
查询中没有任何内容是group by
列表中的别名表达式。
由于select
在没有having
的情况下使用,我的猜测很混乱。因为表达式不在group by
中,所以可能MySQL / MariaDB决定在一个不确定的行上评估它一次,而不是每行一次。两个数据库之间的结果差异可能仅仅是由于选择了行。
在任何情况下,在任何其他数据库中,没有select
的{{1}}通常看起来很尴尬。 <{1}}没有having
且不允许使用聚合函数。
答案 1 :(得分:0)
WHERE和HAVING不可互换。 HAVING只应用作GROUP BY的条件。 MySQL / MariaDB在如何编写SQL方面非常宽松,因此不会发出警告/错误,有时您可能会得到意想不到的结果。
在你的情况下,函数调用似乎在ORDER BY / LIMIT组合之后执行,导致函数只接收值为33的行。