Why does SELECT results differ between mysql and sqlite?

前端 未结 3 1336
你的背包
你的背包 2021-02-12 13:41

I\'m re-asking this question in a simplified and expanded manner.

Consider these sql statements:

create table foo (id INT, score INT);

insert into foo v         


        
3条回答
  •  长发绾君心
    2021-02-12 14:16

    Lets look at this two ways, i'll use postgres 9.0 as my reference database

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

    so you have got to ask yourself -- what do you actually mean when you do this correlated subquery inside a having clause, if it evaluates every row against every row from the primary query we are making a cartesian join and I don't think we should be pointing fingers at the SQL engine.

    if you want every row that is less than the maximum average What you should be saying is:

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

提交回复
热议问题