УСТРАНЕНИЕ ИЗБЫТОЧНОСТИ
Обратите внимание, что наш вывод имеет два значения для каждой комбинации, причем второй раз - в обратном порядке. Это потому что каждое значение показано первый раз в каждом псевдониме, а второй раз (симметрично) - в предикате. Следовательно, значение A в псевдониме сначала выбирается в комбинации со значением B во втором псевдониме, а затем значение A во втором псевдониме выбирается в комбинации со значением B в первом псевдониме. В нашем примере, Hoffman выбран вместе с Clemens, а затем Clemens выбран вместе с Hoffman. Тот же самый случай - с Cisneros и Grass, Liu и Giovanni, и так далее. Кроме того, каждая строка была сравнена сама с собой, чтобы вывести строки, такие как Liu и Liu. Простой способ избежать этого - установить порядок на два значения так, чтобы одно могло быть меньше, чем другое, или предшествовать ему в алфавитном порядке. Это делает предикат асимметричным, поэтому те же самые значения в обратном порядке не будут выбраны снова, например:
SELECT first.cname, second.cname, first.rating FROM Customers first, Customers second WHERE first.rating = second.rating AND first.cname < second.cname;
Вывод этого запроса показан на Рисунке 9.2.
Hoffman предшествует Pereira в алфавитном порядке, поэтому комбинация удовлетворяет обоим условиям предиката и появляется в выводе. Когда та же сама комбинация появляется в обратном порядке - когда Pereira в псевдониме первой таблицы сравнивается с Hoffman во второй таблице псевдонима - второе условие не выполняется. Аналогично Hoffman не выбирается при наличии того же рейтинга, что и у него самого, потому что его имя не предшествует ему самому в алфавитном порядке. Если бы вы захотели включить сравнение строк с ними же самими
=============== SQL Execution Log ============== | | | SELECT first.cname, second.cname, first.rating | | FROM Customers first, Customers second | | WHERE first.rating = second.rating | | AND first.cname < second.cname | | =============================================== | | cname cname rating | | ------- --------- ------- | | Hoffman Pereira 100 | | Giovanni Liu 200 | | Clemens Hoffman 100 | | Pereira Pereira 100 | | Gisneros Grass 300 | =================================================
Рисунок 9.2 Устранение избыточности вывода в объединении с собой
в запросах, подобно этому, вы могли бы просто использовать < = вместо <.