Открийте 10те разлики....
7 отговора
671 прегледа
Открийте 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 странички в документацията с по-подробна информация по въпроса...
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 странички в документацията с по-подробна информация по въпроса...
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
във втория случай слагаш ( 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
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 и после махане на излишните записи които не отговарят на условието"
наистина това в първия случай работи както трябва а това във втория вади всякакви неща от 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 и после махане на излишните записи които не отговарят на условието"
Re: Открийте 10те разлики....
всъщност наясно ли си защо ползваш LEFT JOIN, a не обикновен INNER JOIN? трябва ли ти?
ViruS
ViruS
Re: Открийте 10те разлики....
Защото стандартите се тълкуват много трудно затова ....
Аз така и не успях да разбера къде точно това е описано, но SQL 99 изисква условията да се местят от WHERE в ON и обратно без да променят крайния резултат.
А при MySQL ON се приема само за JOIN условие и ...
Някъде из 4.1 вероятно ще го "поправим"
salle.online.bg/sig
Аз така и не успях да разбера къде точно това е описано, но SQL 99 изисква условията да се местят от WHERE в ON и обратно без да променят крайния резултат.
А при MySQL ON се приема само за JOIN условие и ...
Някъде из 4.1 вероятно ще го "поправим"
salle.online.bg/sig
Re: Открийте 10те разлики....
Много 10х
... с това темата може да се счита за приключена
... с това темата може да се счита за приключена
Priklu4ena ama utre
vse 6te se nameri niakoi prostak da pi6e v neia :-))))
E tuk ni6to niama :[линк]
E tuk ni6to niama :[линк]