При left join би трябвало филтрирането на редовете от отделните таблици да е преди обединяването на данните от тях.
При и select ... from t1,t2,t3 обединяването на данните е пълна комбинация от всички редове от всяка от таблиците, след което се извършва филтриране според where клаузите.
Възможно е някои СБД да оптимизират cross-join заявките до left и right join заявки, но аз лично ще ти препоръчам да си указваш изрично типа на комбиниране на записите от таблиците, по следните причини:
Неоптимизиран (вътрешно от СБД) cross-join в сравнение с left outer/right outer join:
1. ползва повече памет за временни резултати от изпълнение на заявката
2. извършва повече сравнения, тъй като филтрирането се извършва след, а не преди комбинирането на редовете от таблиците.
3. много по-трудно се проследява програмна логика (left outer join автоматично означава релация тип "едно-към-много", респективно right outer join е "много-към-едно"), докато при cross-join-а тези връзки не са явни и трябва да се разглежда where клаузата под лупа.
Представи си cross-join от 9 таблици - 1 главна, 2 подчинени и 6 lookup (т.е. съдържащи еквивалети на кодове/идентификатори с имена/символни низове) как ще изглежда и представи си колко по-ясно ще изглежда същата заявка с 8 left outer join-а.
Вярно че заявката с left outer join ще е по-дълга като текст, но ще е много по-лесно да се ориентираш в нея за какво става въпрос, отколкото в cross-join-а.
Не дай боже да се наложи да правиш и union на два, три и повече резултата от такива заявки.
Освен това при left outer join също можеш да имаш where, но там вече ще сложиш условията за филтриране на резултата от join-а.
Сега се сетих, че ако нямаш еквивалентен ред за даден идентификатор от главната таблица в подчинената/lookup таблицата, то при cross-join ще загубиш този ред, тъй като няма да имаш редове с идентификатор null за подчинената таблица.
Т.е. ако потребителя си е изтрил по погрешка всички редове в подчинената, или еквивалентния ред в lookup таблицата, то този ред от главната таблица, няма да бъде изведен при cross-join с последващ where филтър.
Примерно имаш общи данни за фактура с даден номер, и нямаш нито една позиция все още по тази фактура (т.е. потребителя още не е попълнил редовете с данни за фактурата).
В този случай, ако поиска справка за фактурите заедно с позициите по тях, няма да можеш да покажеш тази фактура и да кажеш че по нея няма позиции ако ползваш cross-join.
Друг пример - имаш таблица която ти дава съответствия по пощенски код и населено място. Ако ползваш пощенския код за идентификатор на населеното място (в главната таблица) и в случай че за дадения пощенски код нямаш съответен в таблицата със съответствия, то при cross-join ще загубиш този ред от главната таблица, докато при left outer join ще имаш null, като име на населеното място.
Накратко казано cross join с where t1.id = t2.id е еквивалентен на inner join, като резултат, но като изпълнение е много по-бавен.
За да реализираш еквивалент на left outer join с cross join-и, трябва да ползваш union и подзаявка с not exists() като условие за нея.
т.е. Обедини (union) всички записи за които t1.id = t2.id с тези записи от t1, за които няма ред в t2, с id = t1.id
За да мине union-а трябва да зададеш изрично null As t2.column1, null As t2.column2 за всяка от колоните от t2, които ти участват в заявката.
Надявам се след това последното да ти е станала поне малко ясна разликата между двете.Редактирано от TPECKATA на 30.03.07 22:08.
|