Квалифицированный выбор при использовании предложений

Таблицы имеют тенденцию становиться очень большими, с течением времени все большее и большее количество строк в нее добавляется. Поскольку обычно из них только определенные строки интересуют вас в данное время, SQL дает возможность вам устанавливать критерии, чтобы определить, какие строки будут выбраны для вывода.

WHERE — предложение команды SELECT, которое позволяет вам устанавливать предикаты, условие которых может быть или верным или неверным для любой строки таблицы. Команда извлекает только те строки из таблицы, для которых такое утверждение верно. Предположим, вы хотите видеть имена и комиссионные всех продавцов в Лондоне. Вы можете ввести такую команду:

SELECT sname, comm
FROM Salespeople
WHERE city = 'London';

Когда предложение WHERE представлено, программа базы данных просматривает всю таблицу по одной строке и исследует каждую строку, чтобы определить, верно ли утверждение. Следовательно, для записи Peel программа рассмотрит текущее значение столбца city, определит, что оно равно 'London', и включит эту строку в вывод. Запись для Serres не будет включена, и так далее. Вывод для вышеупомянутого запроса показан в Рисунке 3.6.

=============== SQL Execution Log ============
| SELECT sname, comm |
| FROM Salespeople |
| WHERE city = 'London' |
| ============================================= |
| sname comm |
| ------- ---------- |
| Peel 0.12 |
| Motika 0.11 |
===============================================

Рисунок 3.6. Оператор SELECT с предложением WHERE

Давайте попробуем пример с числовым полем в предложении WHERE. Поле rating таблицы Заказчиков предназначено, чтобы разделять заказчиков на группы, основанные на некоторых критериях, которые могут быть получены в итоге через этот номер. Возможно это — форма оценки кредита или оценки, основанные на опыте предыдущих приобретений. Такие числовые коды могут быть полезны в реляционных базах данных как способ подведения итогов сложной информации. Мы можем выбрать всех заказчиков с рейтингом 100 следующим образом:

SELECT *
FROM Customers
WHERE rating = 100;

Одиночные кавычки не используются здесь потому, что оценка — это числовое поле. Результаты запроса показаны в Рисунке 3.7.

Предложение WHERE совместимо с предыдущим материалом в этой главе. Другими словами, вы можете использовать номера столбцов, устранять дубликаты, или переупорядочивать столбцы в команде SELECT, которая использует WHERE. Однако, вы можете изменять порядок столбцов для имен только в предложении SELECT, но не в предложении WHERE.

=============== SQL Execution Log ============
| SELECT * |
| FROM Customers |
| WHERE rating = 100; |
| ============================================= |
| сnum cname city rating snum |
| ------ -------- ------ ---- ------ |
| 2001 Hoffman London 100 1001 |
| 2006 Clemens London 100 1001 |
| 2007 Pereira Rome 100 1004 |
===============================================

Рисунок 3.7. Оператор SELECT с числовым полем в предикате.

Резюме

Теперь вы знаете несколько способов заставить таблицу давать вам ту информацию, какую вы хотите, а не просто выбрасывать наружу все ее содержание. Вы можете переупорядочивать столбцы таблицы или устранять любую из них. Вы можете решать, хотите вы видеть дублированные значения или нет.

Наиболее важно то, что вы можете ставить условие, называемое предикатом, которое определяет или не определяет указанную строку таблицы из тысяч таких же строк, будет ли она выбрана для вывода.

Предикаты могут становиться очень сложными, предоставляя вам высокую точность в решении, какие строки вам выбирать с помощью запроса. Именно эта способность решать точно, что вы хотите видеть, делает запросы SQL такими мощными.

Следующие несколько глав будут посвящены, в большей мере, особенностям, которые расширяют мощность предикатов. В Главе 4 вам будут представлены операторы, иные, чем те, которые используются в условиях предиката, а также способы объединения многочисленных условий в единый предикат.

Работа с SQL

1. Напишите команду SELECT, которая бы вывела номер Заказа, сумму, и дату для всех строк из таблицы Заказов.

2. Напишите запрос, который вывел бы все строки из таблицы Заказчиков, для которых номер продавца = 1001.

3. Напишите запрос, который вывел бы таблицу со столбцами в следующем порядке: city, sname, snum, comm.

4. Напишите команду SELECT, которая вывела бы оценку (rating), сопровождаемую именем каждого заказчика в San Jose.

5. Напишите запрос, который вывел бы значения snum всех продавцов в текущем порядке из таблицы Заказов без каких бы то ни было повторений.

(См. Приложение A для ответов.)


Использование реляционных и булевых операторов для создания более изощрённых предикатов

В ГЛАВЕ 3 ВЫ УЗНАЛИ, ЧТО ПРЕДИКАТЫ МОГУТ оценивать равенство оператора как верного или неверного. Они могут также оценивать другие виды связей кроме равенств. Эта глава будет исследовать другие реляционные операторы, используемые в SQL. Вы также узнаете, как использовать операторы Буля, чтобы изменять и объединять значения предиката. С помощью операторов Буля (или, проще говоря, логических операторов), одиночный предикат может содержать любое число условий. Это позволяет вам создавать очень сложные предикаты. Использование круглых скобок в структуре этих сложных предикатов будет также объясняться.

Реляционные операторы

Реляционный оператор — математический символ, который указывает на определенный тип сравнения между двумя значениями. Вы уже видели, как используются равенства, такие как 2 + 3 = 5 или city = 'London'. Но также имеются другие реляционные операторы. Предположим, что вы хотите видеть всех Продавцов с их комиссионными выше определенного значения. Вы можете использовать тип сравнения "больше чем" (>).

Реляционные операторы, которыми располагает SQL:

=Равно

>Больше чем

<Меньше чем

>=Больше чем или равно

<=Меньше чем или равно

<>Не равно

Эти операторы имеют стандартные значения для числовых значений. Для значения символа, их определение зависит от формата преобразования, ASCII или EBCDIC, который вы используете.

SQL сравнивает символьные значения в терминах основных номеров, как определено в формате преобразования. Даже значение символа, такого как '1', который представляет номер, не обязательно равняется номеру, который он представляет. Вы можете использовать реляционные операторы, чтобы установить алфавитный порядок, например, 'a' < 'n' где 'a' первое в алфавитном порядке, но все это ограничивается с помощью параметра преобразования формата.

И в ASCII и в EBCDIC, символы букв по значению меньше, чем все другие символы, которым они предшествуют в алфавитном порядке и имеют один регистр (верхний или нижний). В ASCII все символы верхнего регистра меньше, чем все символы нижнего регистра, поэтому 'Z' < 'a', а все номера меньше, чем все символы, поэтому '1' < 'Z'. То же относится и к EBCDIC. Чтобы сохранить обсуждение более простым, мы допустим, что вы будете использовать текстовый формат ASCII. Проконсультируйтесь с вашей документацией системы, если вы не уверены, какой формат вы используете, или как он работает.

Значения, сравниваемые здесь, называются скалярными значениями. Скалярные значения производятся скалярными выражениями; 1 + 2 — это скалярное выражение, которое производит скалярное значение 3. Скалярное значение может быть символом или числом, хотя очевидно, что только номера используются с арифметическими операторами, такими как + (плюс) или * (звезда).

Предикаты обычно сравнивают значения скалярных величин, используя или реляционные операторы или специальные операторы SQL чтобы увидеть, верно ли это сравнение. Некоторые операторы SQL описаны в Главе 5.

Предположим, что вы хотите увидеть всех заказчиков с оценкой (rating) выше 200. Так как 200 — это скалярное значение, как и значение в столбце оценки, для их сравнения вы можете использовать реляционный оператор.

SELECT *
FROM Customers
WHERE rating > 200;

Вывод для этого запроса показывается в Рисунке 4.1.

=============== SQL Execution Log ============
| SELECT * |
| FROM Customers |
| WHERE rating > 200; |
| ============================================= |
| snum cname city rating snum |
| ----- -------- -------- ----- ------ |
| 2004 Crass Berlin 300 1002 |
| 2008 Cirneros San Jose 300 1007 |
===============================================

Рисунок 4.1. Использование предиката "больше чем" (>)

Конечно, если бы мы захотели увидеть еще и заказчиков с оценкой, равной 200, мы стали бы использовать предикат

rating >= 200

Булевы операторы

Основные Булевы операторы также распознаются в SQL. Выражения Буля — являются или верными, или неверными, подобно предикатам. Булевы операторы связывают одно или более верных/неверных значений и производят единственное верное/или/неверное значение. Стандартными операторами Буля, распознаваемыми в SQL, являются: AND, OR, и NOT.

Существуют другие, более сложные, операторы Буля (типа "исключенный или"), но они могут быть сформированы из этих трех простых операторов — AND, OR, NOT.

Как вы можете понять, Булева верная/неверная логика — основана на цифровой компьютерной операции; и фактически, весь SQL (или любой другой язык) может быть сведен до уровня Булевой логики.

Операторы Буля и как они работают:

AND берет два Буля (в форме A AND B) как аргументы и оценивает их по отношению к истине, верны ли они оба.

OR берет два Буля (в форме A OR B) как аргументы и оценивает на правильность, верен ли один из них.

NOT берет одиночный Булев (в форме NOT A) как аргументы и заменяет его значение с неверного на верное или верное на неверное.

Связывая предикаты с операторами Буля, вы можете значительно увеличить их возможности. Предположим вы хотите видеть всех заказчиков в San Jose которые имеют оценку (рейтинг) выше 200:

SELECT *
FROM Customers
WHERE city = 'San Jose'
AND rating > 200;

Вывод для этого запроса показан на Рисунке 4.2. Имеется только один заказчик, который удовлетворяет этому условию.

=============== SQL Execution Log ============
| |
| SELECT * |
| FROM Customers |
| WHERE city = 'San Jose' |
| AND rating > 200; |
| ============================================= |
| сnum cname city rating snum |
| ------ -------- -------- ---- ----- |
| 2008 Cirneros San Jose 300 1007 |
===============================================

Рисунок 4.2. Оператор SELECT использующий AND

Если вы же используете OR, вы получите всех заказчиков, которые находились в San Jose или (OR) которые имели оценку выше 200.

SELECT *
FROM Customers
WHERE city = 'San Jose' OR rating > 200;

Вывод для этого запроса показывается в Рисунке 4.3.

=============== SQL Execution Log ============
| SELECT * |
| FROM Customers |
| WHERE city = 'San Jose' |
| OR rating > 200; |
| ============================================= |
| сnum cname city rating snum |
| ----- ------- -------- ----- ------ |
| 2003 Liu San Jose 200 1002 |
| 2004 Grass Berlin 300 1002 |
| 2008 Cirneros San Jose 300 1007 |
===============================================

Рисунок 4.3. Оператор SELECT, использующий OR

NOT может использоваться для инвертирования значений Буля. Имеется пример запроса с NOT:

SELECT *
FROM Customers
WHERE city = 'San Jose' OR NOT rating > 200;

Вывод этого запроса показывается в Рисунке 4.4.

=============== SQL Execution Log ============
| SELECT * |
| FROM Customers |
| WHERE city = 'San Jose' |
| OR NOT rating > 200; |
| ============================================= |
| cnum cname city rating snum |
| ------ -------- ------ ----- ----- |
| 2001 Hoffman London 100 1001 |
| 2002 Giovanni Rome 200 1003 |
| 2003 Liu San Jose 200 1002 |
| 2006 Clemens London 100 1001 |
| 2008 Cirneros San Jose 300 1007 |
| 2007 Pereira Rome 100 1004 |
===============================================

Рисунок 4.4. Оператор SELECT, использующий NOT

Все записи, за исключением Grass, были выбраны. Grass не был в San Jose, и его оценка была больше, чем 200, так что он потерпел неудачу при обеих проверках. В каждой из других строк встретился один или другой или оба критериев. Обратите внимание, что оператор NOT должен предшествовать Булеву оператору, чье значение должно измениться, и не должен помещаться перед реляционным оператором. Например, неправильным вводом оценки предиката будет:

rating NOT > 200

Он выдаст другую отметку. А как SQL оценит следующее?

SELECT *
FROM Customers
WHERE NOT city = 'San Jose' OR rating > 200;

NOT применяется здесь только к выражению city = 'San Jose', или к выражению rating > 200 тоже? Как и написано, правильный ответ будет прежним. SQL может применять NOT с выражением Буля только сразу после него. Вы можете получить другой результат при команде:

SELECT *
FROM Customers
WHERE NOT(city = 'San Jose' OR rating > 200);

Здесь SQL понимает круглые скобки как означающие, что все внутри них будет оцениваться первым и обрабатываться как единое выражение с помощью всего, что снаружи них (это является стандартной интерпретацией в математике). Другими словами, SQL берет каждую строку и определяет, соответствует ли истине равенство city = 'San Jose' или равенствоrating > 200. Если любое условие верно, выражение Буля внутри круглых скобок верно. Однако, если выражение Буля внутри круглых скобок верно, предикат как единое целое неверен, потому что NOT преобразует верно в неверно и наоборот.

Вывод для этого запроса показывается в Рисунке 4.5.

=============== SQL Execution Log ============
| SELECT * |
| FROM Customers |
| WHERE NOT (city = 'San Jose' |
| OR rating > 200); |
| ============================================= |
| cnum cname city rating snum |
| ----- -------- ------- ----- ------ |
| 2001 Hoffman London 100 1001 |
| 2002 Giovanni Rome 200 1003 |
| 2006 Clemens London 100 1001 |
| 2007 Pereira Rome 100 1004 |
===============================================

Рисунок 4.5. Оператор SELECT, использующий NOT и вводное предложение

Имеется намеренно сложный пример. Посмотрим, сможете ли вы проследить его логику (вывод показан в Рисунке 4.6):

SELECT *
FROM Orders
WHERE NOT ((odate = 10/03/1990 AND snum >1002) OR amt > 2000.00);

=============== SQL Execution Log ==============
| SELECT * |
| FROM Orders |
| WHERE NOT ((odate = 10/03/1990 AND snum > 1002) |
| OR amt > 2000.00); |
| =============================================== |
| onum amt odate cnum snum |
| ------ -------- ---------- ----- ----- |
| 3003 767.19 10/03/1990 2001 1001 |
| 3009 1713.23 10/04/1990 2002 1003 |
| 3007 75.75 10/04/1990 2004 1002 |
| 3010 1309.95 10/06/1990 2004 1002 |
=================================================

Рисунок 4.6. Полный (комплексный) запрос

Примечание. Для СУБД Interbase запрос должен быть изменен:

SELECT *
FROM Orders
WHERE NOT ((odate = CAST('10/03/1990' AS DATE) AND snum >1002) OR amt > 2000.00);

Несмотря на то, что Булевы операторы индивидуально просты, они не так просты, когда комбинируются в комплексное выражение.

Способ оценки Булева комплекса состоит в том, чтобы оценивать Булевы выражения, наиболее глубоко вложенные в круглых скобках, объединять их в единичное Булево значение, и затем объединять его с верхними значениями.

Имеется подробное объяснение того, как пример выше был вычислен. Наиболее глубоко вложенные выражения Буля в предикате — это odate = 10/03/1990 и snum > 1002 являются объединенными с помощью AND, формируя одно выражение Буля, которое будет оценено как верное для всех строк, в которых встретились оба эти условия. Это составное Булево выражение (которое мы будем называть Булево номер 1, или B1 для краткости) объединяется с выражением (amt) > 2000.00 (B2) с помощью OR, формируя третье выражение (B3), которое является верным для данной строки, если или B1 или B2 — верны для этой строки. B3 полностью содержится в круглых скобках, которым предшествует NOT, формируя последнее выражение Буля (B4), которое является условием предиката. Таким образом, B4, предикат запроса, — будет верен всякий раз, когда B3 неправилен. B3 — неправилен всегда, когда B1 и B2 — оба неверны. B1 неправилен для строки, если дата Заказа строки не 10/03/1990, или если значение snum не большее чем 1002. B2 неправилен для всех строк, значения суммы приобретений которых не превышает 2000.00. Любая строка со значением выше 2000.00 сделает B2 — верным; в результате B3 будет верен, а B4 нет. Следовательно, все эти строки будут удалены из вывода. Из оставшихся, строки, которые на 3 Октября имеют snum > 1002 (такие, как строки для onum 3001 на 3 Октября со snum = 1007), делают B1 верным, с помощью верного B3 и неверного предиката запроса. Они будут также удалены из вывода. Вывод показан для строк, которые оставлены.

Резюме

В этой главе вы значительно расширили ваше знакомство с предикатами. Теперь вы можете находить значения, которые связаны с данным значением любым способом — определяемым различными реляционными операторами. Вы можете также использовать операторы Буля ANDиOR, чтобы много условий, каждое из которых автономно в предикатах, объединять в единый предикат. Оператор Буля NOT, как вы уже видели, может изменять значение условия или группы условий на противоположное.

Булевы и реляционные операторы могут эффективно управляться с помощью круглых скобок, которые определяют порядок, в котором операции будут выполнены. Эти операции применимы к любому уровню сложности, и вы поняли, как сложные условия могут создаваться из этих простых частей.

Теперь, когда мы показали, как используются стандартные математические операторы, мы можем перейти к операторам, которые являются исключительными в SQL. Это мы сделаем в Главе 5.

Работа с SQL

1. Напишите запрос, который может дать вам все Заказы со значениями суммы выше чем $1,000.

2. Напишите запрос, который может выдать вам поля sname и city для всех продавцов в Лондоне с комиссионными выше .10.

3. Напишите запрос к таблице Заказчиков чей вывод может включить всех заказчиков с оценкой =< 100, если они не находятся в Риме.

4. Что может быть выведено в результате следующего запроса?

SELECT *
FROM Orders
WHERE (amt < 1000 OR NOT (odate = 10/03/1990 AND cnum > 2003));

5. Что может быть выведено в результате следующего запроса?

SELECT *
FROM Orders
WHERE NOT ((odate = 10/03/1990 OR snum > 1006) AND amt > = 1500);

6. Как можно проще переписать такой запрос?

SELECT snum, sname, city, comm
FROM Salespeople
WHERE (comm > + .12 OR comm < .14);

(См. Приложение A для ответов.)