Открийте 10те разлики....

7 отговора 671 прегледа
#1

Открийте 10те разлики....

1.
SELECT p.user_id FROM cati_resp_status p
LEFT JOIN cati_sample_129 s ON s.user_id=p.user_id
LEFT JOIN cati_resp_lock r ON r.user_id=s.user_id
WHERE p.status_id = 1003
AND p.contacted = 1
AND p.last_contacted < '20030417195217'
AND r.user_id IS NULL
AND ( s.lang1 IN(10) OR s.lang2 IN(10) OR s.lang3 IN(10) )
AND s.timezone IN(4,5)

2.
SELECT p.user_id FROM cati_resp_status p
LEFT JOIN cati_sample_129 s ON s.user_id=p.user_id
AND ( s.lang1 IN(10) OR s.lang2 IN(10) OR s.lang3 IN(10) )
AND s.timezone IN(4,5)
LEFT JOIN cati_resp_lock r ON r.user_id=s.user_id
WHERE p.status_id = 1003
AND p.contacted = 1
AND p.last_contacted < '20030417195217'
AND r.user_id IS NULL


и двете заявки връщат резултат, но резултатът от едната е доста страннен и определено не е верен...
според EXPLAIN-а и двете заявки би трябвало да се изпълнят по еднакъв начин...

определено в тази ситуация оптимизатора на mysql-a проявява характер и се държи доста странно. май е време някой да седне и да добави 2-3 странички в документацията с по-подробна информация по въпроса...

Отговор
в отговор на 3ъл Oйлюфф #2

Re: Открийте 10те разлики....

наистина ще се изпълнят по един и същ начин, но е нормално резултата да е различен:

във втория случай слагаш ( s.lang1 IN(10) OR s.lang2 IN(10) OR s.lang3 IN(10) )
AND s.timezone IN(4,5) в условието на LEFT JOIN-а, т.е. ако никой от езиците на юзъра не е 10 или зоната не е 4или 5 просто всичките полета от таблица cati_sample_129 s в резултата ще са NULL за този юзър

в първия случай, слагаш гореспоменатото условие във WHERE, т.е. отначало си правиш JOIN-овете, а после WHERE маха редовете на юзърите, на които езика не е 10ка... т.е. с 2 думи 2 този случай получаваш резултат точно като този от INNER JOIN

с 2 думи, не е проблема в MySQL-a

ViruS
Отговор
в отговор на ViruS #3

Re: Открийте 10те разлики....

хубаво ама не съвсем...
наистина това в първия случай работи както трябва а това във втория вади всякакви неща от cati_resp_status които ги няма в cati_sample_129

въпроса е защо слагането на клаузата ( s.lang1 IN(10) OR s.lang2 IN(10) OR s.lang3 IN(10) ) AND s.timezone IN(4,5) в JOIN-a се тълкува от mysql-a като отрицание а не като допълнително ограничаваща условие още преди изпълнението на JOIN-a.
тоест - "JOIN САМО на тези записи от cati_sample_129, за които е изпълнено условието, към таблица cati_resp_status" а не "JOIN на cati_sample_129 и cati_resp_status и после махане на излишните записи които не отговарят на условието"

Отговор
в отговор на 3ъл Oйлюфф #4

Re: Открийте 10те разлики....

всъщност наясно ли си защо ползваш LEFT JOIN, a не обикновен INNER JOIN? трябва ли ти?

ViruS
Отговор
в отговор на ViruS #5

Re: Открийте 10те разлики....

въпросът беше принципен а не защо го използвам....

Отговор
в отговор на 3ъл Oйлюфф #6

Re: Открийте 10те разлики....

Защото стандартите се тълкуват много трудно затова ....

Аз така и не успях да разбера къде точно това е описано, но SQL 99 изисква условията да се местят от WHERE в ON и обратно без да променят крайния резултат.

А при MySQL ON се приема само за JOIN условие и ...
Някъде из 4.1 вероятно ще го "поправим"

salle.online.bg/sig
Отговор
в отговор на salle #7

Re: Открийте 10те разлики....

Много 10х

... с това темата може да се счита за приключена

Отговор
в отговор на 3ъл Oйлюфф #8

Priklu4ena ama utre

vse 6te se nameri niakoi prostak da pi6e v neia :-))))

E tuk ni6to niama :[линк]
Отговор