КАК ANY МОЖЕТ СТАТЬ НЕОДНОЗНАЧНЫМ
Как подразумевалось выше, ANY не полностью однозначен. Если мы создаем
запрос чтобы выбрать заказчиков которые имеют больший рейтинг чем любой заказчик в Риме, мы можем
получить вывод
который несколько отличался бы от того что мы ожидали ( как показано в Рисунке 13.5 ):
SELECT * FROM Customers
WHERE rating > ANY ( SELECT rating FROM Customers WHERE city = Rome );
В английском языке, способ которым мы обычно
склонны интерпретировать оценку " больше чем любой ( где city = Rome ) " , должен вам сообщить что это
значение
оценки должно быть выше чем значение оценки в каждом случае где значение city = Rome. Однако это не так,
в случае ANY -
используемом в SQL . ANY оценивает как верно, если подзапрос находит любое значение которое делает
условие верным.
cnum |
cname |
city |
rating |
snum |
2002 |
Giovanni |
Rome |
200 |
1003 |
2003 |
Liu |
San Jose |
200 |
1002 |
2004 |
Grass |
Berlin |
300 |
1002 |
2008 |
Cisneros |
San Jose |
300 |
1007 |
Рисунок 13.5 Как оператор "больше чем" (>) интерпретируется ANY
Если мы оценим ANY способом использующим грамматику Английского
Язы- ка, то только заказчики с оценкой 300 будут превышать Giovanni, который находится в Риме и имеет
оценку 200.
Однако, подзапрос ANY также находит Periera в Риме с оценкой 100. Так как все заказчики с оценкой 200
были выше этой,
они будут выбраны, даже если имелся другой заказчик из Рима(Giovanni) чья оценка не была выше (
фактически, то что один
из выбранных заказчиков также находится в Риме несущественно). Так как подзапрос произвел по крайней
мере одно
значение которое сделает предикат верным в отношении этих строк, строки были выбраны. Что- бы дать
другой пример,
предположим что мы должны были выбирать все порядки сумм приоретений которые были больше чем по крайней
мере
один из порядков на 6-е Октября:
SELECT * FROM Orders WHERE amt > ANY ( SELECT amt FROM Orders WHERE odate = 10/06/1990 );
Вывод для этого запроса показывается в Рисунке 13.6. Даже если самая высокая сумма приобретений в
таблице
(9891.88) - имелась на 6-е Октября, предыдущая строка имеет более высокое значение суммы чем другая
строка на 6-е
Октября, которая имела значение суммы = 1309.95. Имея реляционный оператор ">=" вместо просто " > ",
эта строка будет
также выбирана, потому что она равна самой себе. Конечно, вы можете использовать ANY с другой SQL
техникой,
например с техникой обьединения. Этот запрос будет находить все порядки со значением суммы меньшей чем
значение
любой суммы для заказчика в San Jose (вывод показывается в Рисунке 13.7):
SELECT * FROM Orders WHERE amt < ANY ( SELECT amt FROM Orders A, Customers b WHERE a.cnum = b.cnum AND b.city = " San Jose' );
Даже если нименьший порядок в
таблице был для заказчика из San Jose, то был второй наибольший; следовательно почти все строки будут
выбраны.
Простой способ запомнить, что < ANY значение меньшее чем наиболь- шее выбранное значение, а > ANY
значение большее
чем наименьшее выбранное значение.
onum |
atm |
odate |
cnum |
snum |
3002 |
1900.10 |
10/03/1990 |
2007 |
1004 |
3005 |
5160.45 |
10/03/1990 |
2003 |
1002 |
3009 |
1713.23 |
10/04/1990 |
2002 |
1003 |
3008 |
4723.00 |
10/05/1990 |
2006 |
1001 |
3011 |
9891.88 |
10/06/1990 |
2006 |
1001 |
Рисунок 13. 6: Выбранное значение больше чем любое(ANY) на 6-е Октября
onum |
atm |
odate |
cnum |
snum |
3001 |
18.69 |
10/03/1990 |
2008 |
1007 |
3003 |
767.10 |
10/03/1990 |
2001 |
1001 |
3002 |
1900.10 |
10/03/1990 |
2007 |
1004 |
3006 |
1098.10 |
10/03/1990 |
2008 |
1007 |
3009 |
1713.23 |
10/04/1990 |
2002 |
1003 |
3007 |
75.10 |
10/04/1990 |
2004 |
1002 |
3008 |
4723.00 |
10/05/1990 |
2006 |
1001 |
3010 |
1309.88 |
10/06/1990 |
2004 |
1002 |
Рисунок 13. 7: Использование ANY с объединением
onum |
atm |
odate |
cnum |
snum |
3002 |
1900.10 |
10/03/1990 |
2007 |
1004 |
3005 |
5160.45 |
10/03/1990 |
2003 |
1002 |
3009 |
1713.23 |
10/04/1990 |
2002 |
1003 |
3008 |
4723.00 |
10/05/1990 |
2006 |
1001 |
3011 |
9891.88 |
10/06/1990 |
2006 |
1001 |
Рисунок 13.8: Использование агрегатной функции вместо
ANY