Вопрос по mysql, sqlite, sql – Почему результаты SELECT отличаются между mysql и sqlite?

20

Я переспрашиваю об этомвопрос в упрощенном и расширенном виде.

Рассмотрим эти 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);

Используя sqlite,select оператор возвращает:

id          avg1      
----------  ----------
106         4.5       
107         4.0       

и MySQL возвращает:

+------+--------+
| id   | avg1   |
+------+--------+
|  106 | 4.5000 |
+------+--------+

Насколько я могу судить, результаты 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);

Почему sqlite возвращает две записи?

Quick update:

Я запустил оператор в отношении последней версии sqlite (3.7.11) и все еще получаю две записи.

Another update:

Я отправил электронное письмо на [email protected] о проблеме.

Я сам играл с VDBE и нашел что-то интересное. Я разделил след выполнения каждого циклаnot exists (по одному на каждую среднюю группу).

Чтобы иметь три средние группы, я использовал следующие утверждения:

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);

Мы ясно видим, что как-то так и должно бытьr:4.5 сталi:5:

enter image description here

Я сейчас пытаюсь понять, почему это так.

Final edit:

Поэтому я достаточно поиграл с исходным кодом 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);  
Error: User Rate Limit Exceededavg2Error: User Rate Limit Exceededavg1Error: User Rate Limit ExceededMAX(T2.score)Error: User Rate Limit ExceededMAX(T1.score)Error: User Rate Limit Exceededscore REALError: User Rate Limit Exceeded ta.speot.is
Error: User Rate Limit ExceededSQL error: no such function: existsError: User Rate Limit ExceededINError: User Rate Limit Exceeded Bathz
Error: User Rate Limit ExceededWHERE, GROUP BYError: User Rate Limit ExceededHAVING. ta.speot.is
Error: User Rate Limit ExceededasError: User Rate Limit Exceededavg(T2.score) as avg2Error: User Rate Limit Exceeded user610650
Error: User Rate Limit Exceeded Mekanik

Ваш Ответ

3   ответа
0

Error: User Rate Limit Exceeded

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 avg(T2.score) > avg(T1.score));

Error: User Rate Limit Exceeded

select T1.*
from
  ( select id, avg(score) avg1
    from foo 
    group by id
  ) T1
where not exists (
    select T2.id, avg(T2.score) avg2
    from foo T2
    group by T2.id
    having avg(T2.score) > avg1);

Error: User Rate Limit ExceededHAVINGError: User Rate Limit Exceeded

select ta.id, ta.avg1
from 
  ( select id, avg(score) avg1
    from foo
    group by id
  ) ta
  JOIN
  ( select avg(score) avg1
    from foo 
    group by id
    order by avg1 DESC
    LIMIT 1
  ) tmp
  ON tmp.avg1 = ta.avg1 
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededJOINError: User Rate Limit Exceeded
Error: User Rate Limit ExceededJOINError: User Rate Limit Exceeded
1

Error: User Rate Limit Exceeded

(1)

-- select rows from foo 

select T1.id, avg(T1.score) avg1
from foo T1
group by T1.id
-- where we don't have any rows from T2
having  not exists (
-- select rows from foo
select T2.id, avg(T2.score) avg2
from foo T2
group by T2.id
-- where the average score for any row is greater than the average for 
-- any row in T1
having avg2 > avg1);

 id  |        avg1        
-----+--------------------
 106 | 4.5000000000000000
(1 row)

then let's move some of the logic inside the subquery, getting rid of the 'not' : (2)

-- select rows from foo 
select T1.id, avg(T1.score) avg1
from foo T1
group by T1.id
-- where we do have rows from T2
having  exists (
-- select rows from foo
select T2.id, avg(T2.score) avg2
from foo T2
group by T2.id
-- where the average score is less than or equal than the average for any row in T1
having avg2 <= avg1);
-- I think this expression will be true for all rows as we are in effect doing a
--cartesian join 
-- with the 'having' only we don't display the cartesian row set

 id  |        avg1        
-----+--------------------
 106 | 4.5000000000000000
 107 | 4.0000000000000000
(2 rows)

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

select T1.id, avg(T1.score) avg1 
from foo T1 group by T1.id
having avg1 not in 
(select max(avg1) from (select id,avg(score) avg1 from foo group by id)) 
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
1

Error: User Rate Limit Exceeded

Error: User Rate Limit ExceededHAVINGError: User Rate Limit Exceeded

Error: User Rate Limit Exceededavg1Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

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);

Error: User Rate Limit Exceeded

...
having not exists (
    SELECT 1 AS col1 GROUP BY col1 HAVING avg1 <> 5.0);

Error: User Rate Limit ExceededError: User Rate Limit Exceeded.

Error: User Rate Limit Exceeded

Похожие вопросы