<? include 'head.php' ?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head>
<link rel="stylesheet" href="css.css" type="text/css">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<meta http-equiv="Content-Language" content="ru">
<title>Глава 4.</title></head>
<body>
<h1>Глава 4. ИСПОЛЬЗОВАНИЕ РЕЛЯЦИОННЫХ<br>
И БУЛЕВЫХ ОПЕРАЦИЙ ДЛЯ СОЗДАНИЯ<br>
БОЛЕЕ СЛОЖНЫХ ПРЕДИКАТОВ</h1>
<hr width="50%">
<p>В <a href="ch3.php">Главе 3</a> вы узнали, что предикаты могут оценивать 
равенство в операции как true/верное или false/неверное. Они могут также оценивать другие 
виды связей, помимо равенств.</p>
<p>Эта глава будет исследовать другие реляционные 
операции, используемые в SQL. Вы также узнаете, как использовать булевы операции, 
чтобы изменять и объединять значения предиката. С помощью булевых операций  (или, 
проще говоря, логических операций) одиночный предикат может содержать любое 
число условий. Это позволяет  создавать очень сложные предикаты. 
Использование круглых скобок в структуре этих сложных предикатов будет также разъясняться.</p>
<a name="4.1"></a>
<h3>РЕЛЯЦИОННЫЕ ОПЕРАЦИИ</h3>
<p>Реляционная операция - математический символ, который указывает на 
определённый тип сравнения двух значений. Вы уже видели, как используются 
равенства, такие как 2 + 3 = 5 или city = &quot;London&quot;. Но имеются также и другие 
реляционные операции. Предположим, что вы хотите видеть всех Продавцов с их 
комиссионными, выше определенного значения. Вы можете использовать тип сравнения 
&quot;больше чем&quot; (&gt;). Вот реляционные операции (операции 
сравнения), которыми располагает SQL:</p>
<dl><dt>=</dt><dd>Равно</dd><dt>&gt;</dt><dd>Больше</dd><dt>&lt;</dt><dd>Меньше</dd>
<dt>&gt;=</dt><dd>Больше  или равно</dd><dt>&lt;=</dt><dd>Меньше  или равно</dd><dt>&lt;&gt;</dt><dd>Не равно</dd></dl>
<p>Эти операции имеют стандартное значение для чисел. Для  символов их определение зависит от формата преобразования, ASCII или EBCDIC, который вы используете.</p>
<p>SQL сравнивает символьные значения в терминах основных чисел, как определено в формате преобразования. Даже значение символа, такого как &quot;1&quot;, который 
представляет число, не обязательно равняется числу, которое он представляет. Вы можете использовать реляционные операции, чтобы установить алфавитный порядок, 
например, &quot;a&quot; &lt; &quot;n&quot;, где a идёт раньше в алфавитном порядке, но всё это 
ограничивается с помощью параметра преобразования формата.</p>
<p>И в ASCII, и в EBCDIC символы сортируются по значению: символ имеет значение меньше, чем все другие символы, 
которым он предшествует в алфавитном порядке и которые имеют с ним один вариант 
регистра (верхний или нижний). В ASCII все символы верхнего регистра  меньше, чем все символы 
нижнего регистра, поэтому &quot;Z&quot; &lt; &quot;a&quot;, а все числа - меньше чем все символы, 
поэтому &quot;1&quot; &lt; &quot;Z&quot;. То же относится и к EBCDIC.</p>
<p>Чтобы сохранить обсуждение более 
простым, мы допустим, что вы будете использовать текстовый формат ASCII. Проконсультируйтесь в документации вашей системы, если вы не уверены, какой 
формат вы используете или как он работает.</p><p>Значения, сравниваемые здесь, называются скалярными значениями. Скалярные 
значения производятся скалярными выражениями; 1 + 2 это скалярное выражение, которое производит скалярное значение 3. Скалярное значение может быть символом 
или числом, хотя очевидно, что только числа используются с арифметическими операциями, такими как + (сложение) или * (умножение).</p>
<p>Предикаты обычно сравнивают значения скалярных величин, используя реляционные операции или специальные операции SQL, чтобы увидеть, верно ли это сравнение. 
Некоторые операции/операторы SQL описаны в <a href="ch5.php">Главе 5</a>.</p><p>Предположим, что вы хотите увидеть всех заказчиков с оценкой (rating) выше 
200. Так как 200 - скалярное значение, как и значение в столбце оценки, для их сравнения вы можете использовать реляционную операцию.</p>
<pre>    SELECT *
       FROM Customers
       WHERE rating &gt; 200;</pre>
<p>Вывод для этого запроса показан на Рисунке 4.1.</p>
<p>Конечно, если бы мы захотели увидеть ещё и заказчиков с оценкой, равной 200, мы 
использовали бы предикат</p>
<pre>             rating &gt; = 200</pre>
<a name="4.2"></a>
<h3>БУЛЕВЫ ОПЕРАЦИИ</h3>
<p>Основные булевы операции также распознаются в SQL. Выражения Буля являются или верными/true, или неверными/false, подобно предикатам. Булевы операции связывают одно 
или более верных/неверных значений и производят единственное верное или неверное значение.</p>
<p>Стандартными булевыми операциями, распознаваемыми в SQL, являются AND, OR и NOT.</p>
<pre>               ===============  SQL Execution Log ============
              |                                               |
              | SELECT *                                      |
              | FROM  Customers                               |
              | WHERE rating &gt; 200;                           |
              | ============================================= |
              |   snum     cname    city       rating  snum   |
              |  -----   --------  --------   -----    -----  |
              |   2004     Crass    Berlin     300     1002   |
              |   2008     Cirneros San Jose   300     1007   |
                =============================================

		 Рисунок 4.1 Использование операции &quot;больше&quot; (&gt;)</pre>
<p>Существуют другие, более сложные булевы операции (типа &quot;исключающее ИЛИ&quot;), но они могут быть сформированы из этих трёх простых операций - AND, OR, NOT.</p>
<p>Как вы можете понять, булева логика верно/неверно  основана на цифровой компьютерной операции; и фактически весь SQL (или любой другой язык) может 
быть сведён до уровня булевой логики.</p><p>Булевы операции, и как они работают:</p>
<ul><li>AND берет два булевых значения (в форме A AND B) как аргументы и оценивает, верны ли они оба.</li>
<li>OR берет два булевых значения (в форме A OR B) как аргументы и оценивает, верен ли один из них.</li>
<li>NOT берет одиночное булево значение (в форме NOT A) как аргумент и заменяет его значение с неверного на верное или с верного на неверное 
(инвертирует).</li></ul>
<p>Связывая предикаты с булевыми операциями, вы можете значительно расширить их возможности. Предположим, вы хотите видеть всех заказчиков в San Jose, которые 
имеют оценку (рейтинг) выше 200:</p>
<pre>         SELECT  *
            FROM Customers
            WHERE city = &quot; San Jose'
            AND rating &gt; 200;</pre>
<p>Вывод для этого запроса показан на Рисунке 4.2. Имеется только один заказчик, который удовлетворяет этому условию.</p>
<pre>               ===============  SQL Execution Log ============
              |                                               |
              | SELECT *                                      |
              | FROM  Customers                               |
              | WHERE city = 'San Jose'                       |
              | AND rating &gt; 200;                             |
              | ============================================= |
              |   сnum     cname    city     rating    snum   |
              |  ------   --------  --------  ----    -----   |
              |   2008     Cirneros San Jose   300     1007   |
                =============================================

		   Рисунок 4.2 SELECT, использующий AND
 </pre>
<p>Если  же вы используете OR, вы получите всех заказчиков, которые находились в San Jose или (OR) которые имели оценку выше 200.</p>
<pre>           SELECT *
              FROM Customers
              WHERE city = &quot; San Jose'
              OR rating &gt; 200;</pre>
<p>Вывод для этого запроса показан на Рисунке 4.3.</p>
<pre>               ===============  SQL Execution Log ============
              |                                               |
              | SELECT *                                      |
              | FROM  Customers                               |
              | WHERE city = 'San Jose'                       |
              | OR rating &gt; 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</pre>
<p>NOT может использоваться для инвертирования 
булевых значений.</p>
<p>Имеется пример запроса с NOT:</p>
<pre>                    SELECT *
                       FROM Customers
                       WHERE city = &quot; San Jose'
                       OR NOT rating &gt; 200;</pre>
<p>Вывод этого запроса показан на Рисунке 4.4.</p>
<pre>               ===============  SQL Execution Log ============
              |                                               |
              | SELECT *                                      |
              | FROM  Customers                               |
              | WHERE city = 'San Jose'                       |
              | OR NOT rating &gt; 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</pre>
<p>Все записи, за исключением Grass, были выбраны. Grass не был в San Jose, и его оценка была больше, чем 200, так что он потерпел неудачу при обеих проверках. В 
каждой из других строк встретился тот или другой, или оба критерия.<br>
Обратите внимание, что операция NOT должна предшествовать булевой операции, чьё значение 
должно измениться, и не должна помещаться перед реляционной операцией. Например: неправильным вводом  предиката оценки будет:</p>
<pre>                 rating NOT &gt; 200</pre>
<p>Он выдаст другую отметку. А как SQL оценит следующее?</p>
<pre>                   SELECT *
                      FROM Customers
                      WHERE NOT city = &quot; San Jose'
                      OR rating &gt; 200;</pre>
<p>NOT применяется здесь только к выражению city = 'SanJose', или к выражению rating &gt; 200 тоже? Как 
уже было сказано, правильный ответ будет прежним: SQL может 
применять NOT с булевым выражением, которое идёт  только сразу после него. Вы можете получить другой результат при команде:</p>
<pre>                   SELECT *
                      FROM Customers
                      WHERE NOT(city = &quot; San Jose'
                      OR rating &gt; 200);</pre>
<p>Здесь SQL понимает круглые скобки как означающие, что всё внутри них будет 
вычисляться в первую очередь и обрабатываться как единое выражение с помощью всего, что 
снаружи них (это является стандартной интерпретацией, как в математике). Другими словами, SQL берет каждую строку и определяет, соответствует ли истине равенство city 
=&nbsp; 'San Jose' или равенство rating &gt; 200.<br>
Если любое условие верно, булево выражение  внутри круглых скобок верно. Однако, 
если булево выражение внутри круглых скобок верно, предикат как единое целое неверен, потому что NOT преобразует верно в неверно и наоборот.</p>
<p>Вывод для этого запроса показан на Рисунке 4.5. Имеется намеренно усложнённый 
пример. Сможете ли вы проследить его логику (вывод показан на Рисунке 4.6)?</p>
<pre>        SELECT *
           FROM Orders
             WHERE NOT ((odate = 10/03/1990 AND snum &gt;1002)
                OR amt &gt; 2000.00);

               ===============  SQL Execution Log ============
              |                                               |
              | SELECT *                                      |
              | FROM  Customers                               |
              | WHERE NOT  (city = 'San Jose'                 |
              | OR rating &gt; 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 и вводное предложение


               ===============  SQL Execution Log ==============
              |                                                 |
              | SELECT *                                        |
              | FROM  Orders                                    |
              | WHERE NOT ((odate = 10/03/1990 AND snum &gt; 1002) |
              | OR amt &gt; 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 Полный (комплексный) запрос</pre>
<p>Несмотря на то что булевы операции по отдельности просты, они не так просты, когда комбинируются в комплексное выражение.</p>
<p>Способ оценки булева комплекса  состоит в том, чтобы оценивать булевы выражения, наиболее глубоко вложенные в круглых скобках, объединять их в 
единое булево значение, а затем объединять его с вышележащими значениями.</p><p>
Вот подробное объяснение того, как пример выше был вычислен. Наиболее 
глубоко вложенные булевы выражения, в предикате это odate = 10/03/1990 и snum &gt; 1002, 
объединяются с помощью AND, формируя одно булево выражение, которое 
будет оценено как верное для всех строк, в которых встретились оба эти условия. Это составное булево выражение (которое мы будем называть булево номер 1, или B1, 
для краткости) объединяется с выражением (amt) &gt; 2000.00 (B2) с помощью OR, формируя третье выражение (B3), которое является верным для данной строки, если 
или B1 или B2  верны для этой строки.</p><p>B3 полностью содержится в круглых скобках, которым предшествует NOT, формируя 
последнее булево выражение  (B4), которое является условием предиката.</p><p>Таким образом, B4 - предикат запроса - будет верен всякий раз, когда B3 
неправилен. B3  неправилен всегда, когда B1 и B2 оба неверны. B1 неправилен для строки, если дата  строки заказа не 10/03/1990 или если значение snum не 
больше, чем 1002. B2 неправилен для всех строк, значение суммы приобретений которых не превышает 2000.00. Любая строка со значением выше 2000.00 сделает B2  
верным; в результате B3 будет верен, а B4 - нет. Следовательно, все эти строки будут удалены из вывода.</p>
<p>Из оставшихся, строки, которые на 3 октября имеют snum &gt; 1002 (такие как строки для onum 3001 на 3 
октября с snum = 1007), делают B1 верным с помощью 
верного B3 и неверного предиката запроса. Они будут также удалены из вывода. Вывод показан для строк, которые оставлены.<a name="4.3"></a></p>
<h3>РЕЗЮМЕ</h3>
<p>В этой главе вы значительно расширили ваше знакомство с предикатами. Теперь вы можете находить значения, которые связаны с данным значением любым способом, 
определяемым различными реляционными операциями.</p><p>Вы можете также использовать булевы операции AND и OR, чтобы 
несколько условий, 
каждое из которых автономно в предикатах, объединять в единый предикат.</p><p>Булева операция NOT, как вы уже видели, может изменять значение условия или 
группы условий на противоположное.</p><p>Булевы и Реляционные операции могут эффективно управляться с помощью круглых 
скобок, которые определяют порядок, в котором операции будут выполнены. Эти операции применимы к любому уровню сложности, и вы поняли, как сложные условия 
могут создаваться из этих простых частей.</p><p>Теперь, когда мы показали, как 
используются стандартные математические операции, мы можем перейти к операциям 
которые являются специфичными для SQL. Это мы сделаем в <a href="ch5.php">Главе 5</a>.</p>
<a name="4.4"></a>
<h3>РАБОТА СО SQL</h3>
<ol><li>  <pre>Напишите запрос, который может выдать вам все заказы со значениями суммы выше $1,000.</pre></li>
<li><pre>Напишите запрос, который может выдать вам поля sname и city для всех продавцов
в Лондоне с комиссионными выше .10.</pre></li>
<li><pre>Напишите запрос к таблице Заказчиков, чей вывод включит всех заказчиков
с оценкой =&lt; 100, если они не находятся в Риме.</pre></li>
<li><pre>Что может быть выведено в результате следующего запроса?</pre>
  <pre>              SELECT *
                 FROM Orders
                 WHERE (amt &lt; 1000 OR
                     NOT (odate = 10/03/1990
                         AND cnum &gt; 2003));</pre></li>
<li><pre>Что может быть выведено в результате следующего запроса?</pre>
  <pre>              SELECT *
                 FROM Orders
                 WHERE NOT ((odate = 10/03/1990 OR snum &gt; 1006)
                    AND amt &gt; = 1500 );</pre></li>
<li><pre>Как можно проще переписать такой запрос?</pre>
  <pre>              SELECT snum, sname, city, comm
                 FROM Salespeople
                 WHERE (comm &gt; + .12 OR
                    comm &lt; .14);</pre></li></ol>
<pre>(См. ответы в<a href="a.php#4"> Приложении A</a>.)</pre></body></html>
<? include 'foot.php' ?>