Опубликован: 28.12.2011 | Доступ: свободный | Студентов: 7561 / 1027 | Оценка: 3.81 / 3.53 | Длительность: 19:30:00
ISBN: 978-5-9963-0488-2

Лекция 5: Выборка данных. Общее построение предложения SELECT и фразы FROM и WHERE

Аннотация: Рассматриваются общие принципы построения и отработки предложения SELECT. Приводятся правила построения фразы FROM для указания источников данных и фразы WHERE для отбора строк.

Выборка данных

Бескозырка белая, в полоску воротник...

Пионеры смелые спросили напрямик:

"С какого, парень, года, с какого парохода

И на каких морях ты побывал, моряк?"

Артековская песня, слова 3. Александровой, обработка В. Моделя

Фразы предложения SELECT

Предложение SELECT в SQL складывается из фрагментов, которые по примеру лингвистики носят название фраз (clauses). Иногда их удобно называть более общим словом "конструкции" или же словами "часть предложения".

Допустимые в предложении SQL фразы — это: SELECT, FROM, WHERE, GROUP BY, HAVING, CONNECT BY, ORDER BY, PIVOT/UNPIVOT. Общие правила использования фраз в предложении SELECT следующие:

  • В каждом предложении обязаны быть фразы SELECT и FROM. Остальные фразы необязательны.
  • Порядок следования фраз во всех предложениях фиксирован (например, GROUP BY всегда следует за WHERE и FROM, а ORDER BY всегда стоит в конце).
  • Фраза HAVING может употребляться только в дополнении ко GROUP BY.

Начиная с версии 10 в Oracle SQL возможно еще употребление фразы MODEL, которая, однако, стоит особняком от прочих в силу своей синтаксической инородности и нетрадиционности для SQL. Сфера ее применения также специфична — это базы типа "склады данных", data warehouse. Ниже она не рассматривается.

Кроме этого может иметься фраза WITH, которую можно рассматривать как оформительскую (с версии 9) и процедурную (с версии 11.2) надстройку над "традиционным" предложением SELECT. Она рассматривается в соответствующем разделе ниже.

Логический порядок обработки предложения SELECT

Порядок обработки предложения SELECT также фиксирован и почти совпадает с порядком написания фраз в тексте. Исключения составляет (а) фраза SELECT, которая в отличие от написания обрабатывается в последнюю очередь, и (б) фразы CONNECT BY и WHERE, которые обрабатываются в порядке, обратном написанию:


[11-) с версии 11

Указанный порядок — логический. Это значит, что технические планы обработки запросов СУБД может предлагать самые разнообразные, и вовсе не обязательно они будут точно воспроизводить приведенную выше последовательность в каждом отдельном случае. Причина — в чудовищной затратности, которой чревато простое следование вышеприведенной схеме. Однако действие любого плана, фактически предлагаемого Oracle, никогда не будет вступать в противоречие с этой логикой обработки. Иными словами, когда программисту требуется понять, каким может оказаться результат запроса, он вполне вправе положиться на эту общую логическую последовательность обработки и не вдаваться в подробности фактического плана выполнения.

Она основывается на чередовании этапов вычисления (очередная фраза), так что каждый этап принимает какое-то множество данных на входе и вырабатывает множество данных на выходе. За исключением двух крайних случаев: множества данных на входе фразы FROM и окончательного результата на выходе фразы SELECT, — такие множества можно назвать промежуточными результатами вычислений в предложении SELECT. Вот как выглядит логическая схема обработки предложения SELECT, пожалуй самого распространенного вида SELECT … FROM a, b WHERE условие:


В частности, эта схема способна показать, что порядок указания источников данных во фразе FROM никак не сказывается на результате.

Далее приводятся два примера предсказания ответа путем применения техники последовательности промежуточных вычислений.

Пример 1 предложения SELECT

"Выдать в порядке приема на работу всех продавцов с их окладами":

SELECT   ename, sal
FROM     emp
WHERE    job = 'SALESMAN'
ORDER BY hiredate

(Здесь предполагается, что данные о всех сотрудниках исчерпываются таблицей EMP. В базе, отличной от схемы SCOTT, где не соблюдена ортогонализация данных, это может оказаться и не так).

Промежуточный результат после фраз FROM и WHERE

В силу того что источник данных для запроса в данном случае один, фраза FROM фактически ничего не вычисляет, а просто "берет" данные таблицы EMP из базы. Реальную работу — отсев строк согласно условию — выполняет фраза WHERE:

  EMPNO ENAME      JOB             MGR HIREDATE        SAL      COMM    DEPTNO
------- ---------- --------- --------- --------- --------- --------- ---------
   7499 ALLEN      SALESMAN       7698 20-FEB-81      1600       300        30
   7521 WARD       SALESMAN       7698 22-FEB-81      1250       500        30
   7654 MARTIN     SALESMAN       7698 28-SEP-81      1250      1400        30
   7844 TURNER     SALESMAN       7698 08-SEP-81      1500         0        30
Промежуточный результат после фразы ORDER BY

На множестве строк, полученных от WHERE, фраза ORDER BY наводит порядок:

  EMPNO ENAME      JOB             MGR HIREDATE        SAL      COMM    DEPTNO
------- ---------- --------- --------- --------- --------- --------- ---------
   7499 ALLEN      SALESMAN       7698 20-FEB-81      1600       300        30
   7521 WARD       SALESMAN       7698 22-FEB-81      1250       500        30
   7844 TURNER     SALESMAN       7698 08-SEP-81      1500         0        30
   7654 MARTIN     SALESMAN       7698 28-SEP-81      1250      1400        30
Ярослав Прозоров
Ярослав Прозоров

В лекции № 7 "Введение в Oracle SQL" в подразделе "Несамостоятельность группировки с обобщениями ROLLUP, CUBE и GROUPING SETS"  представленная таблица сравнения содержит ошибки - окончания запросов пропущены. Видимо, ошибки вызваны некорректным переносом материала лекции.

Володимир Миколайчук
Володимир Миколайчук
Помогите разобраться поетапно с логикой запроса
-------TOOLS
NAME PRICE TYPE
drill 155 A
sawzall 192 N
mitre saw 292 M
router 86 I
RAD 145 M
jigsaw 128 I
screwdriver 77 P
------TOOL_TYPES
TYPE USAGE
A Always
I Often
M Sometimes
N Rarely
P Never

Запрос SQL:
SELECT t.type, SUM(t.price)
FROM tools t
GROUP BY t.type
HAVING SUM(t.price) >= (SELECT AVG(price)
FROM tools
WHERE type IN (SELECT type
FROM tool_types
WHERE usage = 'Often'));

И сколько строк он все таки вернет