为什么mysql和sqlite之间的SELECT结果不同?

20 mysql sql sqlite

我以简化和扩展的方式重新提出这个问题.

考虑这些sql语句:

create table foo (id INT, score INT);

insert into foo values (106, 4);
insert into foo values (107, 3);
insert into foo values (106, 5);
insert into foo values (107, 5);

select T1.id, avg(T1.score) avg1
from foo T1
group by T1.id
having not exists (
    select T2.id, avg(T2.score) avg2
    from foo T2
    group by T2.id
    having avg2 > avg1);
Run Code Online (Sandbox Code Playgroud)

使用sqlite,select语句返回:

id          avg1      
----------  ----------
106         4.5       
107         4.0       
Run Code Online (Sandbox Code Playgroud)

和mysql返回:

+------+--------+
| id   | avg1   |
+------+--------+
|  106 | 4.5000 |
+------+--------+
Run Code Online (Sandbox Code Playgroud)

据我所知,mysql的结果是正确的,sqlite是不正确的.我尝试real使用sqlite转换为如下所示,但它仍然返回两个记录:

select T1.id, cast(avg(cast(T1.score as real)) as real) avg1
from foo T1
group by T1.id
having not exists (
    select T2.id, cast(avg(cast(T2.score as real)) as real) avg2
    from foo T2
    group by T2.id
    having avg2 > avg1);
Run Code Online (Sandbox Code Playgroud)

为什么sqlite会返回两条记录?

快速更新:

我针对最新的sqlite版本(3.7.11)运行了声明,仍然获得了两条记录.

另一个更新:

我发送了一封关于这个问题的电子邮件到sqlite-users@sqlite.org.

我自己,我一直在玩VDBE,发现了一些有趣的东西.我分割了每个循环的执行跟踪not exists(每个avg组一个).

为了拥有三个平均组,我使用了以下语句:

create table foo (id VARCHAR(1), score INT);

insert into foo values ('c', 1.5);
insert into foo values ('b', 5.0);
insert into foo values ('a', 4.0);
insert into foo values ('a', 5.0);

PRAGMA vdbe_listing = 1;
PRAGMA vdbe_trace=ON;

select avg(score) avg1
from foo
group by id
having not exists (
    select avg(T2.score) avg2
    from foo T2
    group by T2.id
    having avg2 > avg1);
Run Code Online (Sandbox Code Playgroud)

我们清楚地看到应该r:4.5变成什么i:5:

在此输入图像描述

我现在正试图明白为什么会这样.

最终编辑:

所以我一直在玩sqlite源代码.我现在对这种野兽的理解要好得多,虽然我会让原始的开发者对它进行排序,因为他似乎已经在做了这件事:

http://www.sqlite.org/src/info/430bb59d79

有趣的是,至少对我来说,似乎较新的版本(在我使用的版本之后的某些时候)支持插入在上述提交中添加的测试用例中使用的多个记录:

CREATE TABLE t34(x,y);
INSERT INTO t34 VALUES(106,4), (107,3), (106,5), (107,5);  
Run Code Online (Sandbox Code Playgroud)

Mek*_*nik 1

我试图搞乱查询的一些变体。

看起来,sqlite 在嵌套HAVING表达式中使用先前声明的字段时出现错误。

在你的例子avg1中,第二个拥有总是等于 5.0

看:

select T1.id, avg(T1.score) avg1
from foo T1
group by T1.id
having not exists (
    SELECT 1 AS col1 GROUP BY col1 HAVING avg1 = 5.0);
Run Code Online (Sandbox Code Playgroud)

该查询不返回任何内容,但执行以下查询会返回两条记录:

...
having not exists (
    SELECT 1 AS col1 GROUP BY col1 HAVING avg1 <> 5.0);
Run Code Online (Sandbox Code Playgroud)

我在sqlite Tickets list中找不到任何类似的错误。