Шаг 19 - Подводим итог по запросам!

Итак, наконец, одно из направлений, а именно однотабличные запросы, мы, наконец, закончили! Теперь давайте подведем маленький итог и сформулируем правила выполнения однотабличных запросов. В принципе такой тип запросов легко читаем, достаточно внимательно посмотреть на оператор SELECT и, как правило, становиться все ясно, тем не менее, давайте опишем все сухими постулатами! Иногда это полезно! Итак:

  1. ВЗЯТЬ ТАБЛИЦУ, УКАЗАННУЮ В ОПЕРАТОРЕ FROM.
  2. ЕСЛИ ИМЕЕТСЯ ПРЕДЛОЖЕНИЕ WHERE, ПРИМЕНИТЬ ЗАДАННОЕ В НЕМ УСЛОВИЯ ПОИСКА К КАЖДОЙ СТРОКЕ ТАБЛИЦЫ И ОСТАВИТЬ ТОЛЬКО ТЕ СТРОКИ, ДЛЯ КОТОРЫХ ЭТО УСЛОВИЕ ВЫПОЛНЯЕТСЯ, Т.Е. ИМЕЕТ ЗНАЧЕНИЕ TRUE(!). СТРОКИ, ДЛЯ КОТОРЫХ УСЛОВИЕ ПОИСКА ИМЕЕТ ЗНАЧЕНИЕ FALSE ИЛИ NULL - ОТБРОСИТЬ.
  3. ДЛЯ КАЖДОЙ ИЗ ОСТАВШИХСЯ СТРОК ВЫЧИСЛИТЬ ЗНАЧЕНИЕ КАЖДОГО ЭЛЕМЕНТА В СПИСКЕ ВОЗВРАЩАЕМЫХ СТОЛБЦОВ И СОЗДАТЬ ОДНУ СТРОКУ ТАБЛИЦЫ РЕЗУЛЬТАТОВ ЗАПРОСА. ПРИ КАЖДОЙ ССЫЛКЕ НА СТОЛБЕЦ ИСПОЛЬЗУЕТСЯ ЗНАЧЕНИЕ СТОЛБЦА ДЛЯ ТЕКУЩЕЙ СТРОКИ.
  4. ЕСЛИ УКАЗАНО КЛЮЧЕВОЕ СЛОВО DISTINCT, УДАЛИТЬ ИЗ ТАБЛИЦЫ РЕЗУЛЬТАТОВ ЗАПРОСА ВСЕ ПОВТОРЯЮЩИЕСЯ СТРОКИ.
  5. ЕСЛИ ИМЕЕТСЯ ПРЕДЛОЖЕНИЕ ORDER BY ОТСОРТИРОВАТЬ РЕЗУЛЬТАТЫ ЗАПРОСА.

Вот в принципе такие правила, может быть витиевато, но на то они и правила. Если вы будете их придерживаться, то все будет замечательно и проблем не возникнет!!! :) Прежде чем начинать новую тему, давайте рассмотрим, оператор UNION, он позволяет объеденить результаты двух запросов. Тем более что, как раз он и предварит тему многотабличных запросов. Сказать честно, я за всю свою практику такую систему объеденения двух SELECT'ов не применял, хотя может кому-то это и нужно! :)))

Давайте рассмотрим для начала два простых запроса, первый: Вывести список всех товаров, цены которых превышают $500.

SQL> SELECT MFR_ID, PRODUCT_ID
  2     FROM PRODUCTS
  3  WHERE PRICE > 500.00
  4  /

MFR PRODU
--- -----
IMM 779C
BIC 41003
REI 2A44L
IMM 775C
ACI 4100Z
REI 2A44R
IMM 773C

7 строк выбрано.

Получаем следующее. 7 строк и два столбца.

А теперь второй запрос: Вывести список всех товаров, которых было заказано более чем $4.0 за один раз.

SQL> SELECT DISTINCT MFR, PRODUCT
  2     FROM ORDERS
  3  WHERE AMOUNT > 4.00
  4  /

MFR PRODU
--- -----
ACI 41002
ACI 41004
ACI 4100X
ACI 4100Y
ACI 4100Z
BIC 41003
IMM 775C
IMM 779C
QSA XK47
REI 2A44L
REI 2A44R
REI 2A45C

12 строк выбрано.

Получаем 12 строк и два столбца.

А вот теперь применим UNION! Вывести список всех товаров, цены которых превышают $500 или которых было заказано более чем $4.0 за один раз.

SQL> SELECT MFR_ID, PRODUCT_ID
  2     FROM PRODUCTS
  3  WHERE PRICE > 500.00
  4  UNION
  5  SELECT DISTINCT MFR, PRODUCT
  6     FROM ORDERS
  7  WHERE AMOUNT > 4.00
  8  /

MFR PRODU
--- -----
ACI 41002
ACI 41004
ACI 4100X
ACI 4100Y
ACI 4100Z
BIC 41003
IMM 773C
IMM 775C
IMM 779C
QSA XK47
REI 2A44L
REI 2A44R
REI 2A45C

13 строк выбрано.

Интересно, правда, 13 строк и два столбца, а почему их не 19ть? Ведь один из запросов вернул, 7мь, а второй 12ть! Вот в этом и есть объединение, посмотрите внимательнее на значения в первом и втором запросе:

MFR PRODU
--- -----
IMM 779C
BIC 41003
REI 2A44L
IMM 775C
ACI 4100Z
REI 2A44R
IMM 773C


MFR PRODU
--- -----
ACI 41002
ACI 41004
ACI 4100X
ACI 4100Y
ACI 4100Z
BIC 41003
IMM 775C
IMM 779C
QSA XK47
REI 2A44L
REI 2A44R
REI 2A45C

Правда, много похожего, а объедененый не стал повторяться, а просто показал 13ть строк, вот и все! При таком запросе возвращаемые столбцы, если они повторяются, то повторяющиеся столбцы просто отбрасываются. Так как при действии предложения DISTINCT хотя в одном из запросов он присутствует явно! Главное, чтобы запросы содержали одинаковое количество столбцов и тип столбцов в обоих запросах был одинаковый! И еще ORDER BY в таких запросах не применяется! А вот если, все таки нужно вернуть все строки объедененного запроса, то просто укажите ALL после оператора UNION:

SQL> SELECT MFR_ID, PRODUCT_ID
  2  FROM PRODUCTS
  3  WHERE PRICE > 500.00
  4  UNION ALL
  5  SELECT DISTINCT MFR, PRODUCT
  6  FROM ORDERS
  7  WHERE AMOUNT > 4.00
  8  /

MFR PRODU
--- -----
IMM 779C
BIC 41003
REI 2A44L
IMM 775C
ACI 4100Z
REI 2A44R
IMM 773C
ACI 41002
ACI 41004
ACI 4100X
ACI 4100Y
ACI 4100Z
BIC 41003
IMM 775C
IMM 779C
QSA XK47
REI 2A44L
REI 2A44R
REI 2A45C

19 строк выбрано.

Оп! Вот и все 19ть строк! Что и требовалось! Теперь надеюсь стало понятно. Единственное скажу, что удаление повторяющихся строк, в таких запросах, занимает много времени, так как эти типы запросов ресурсоемки! :) Хоть я и говорил, что ORDER BY не используют, можно в принципе, попробовать следующее:

SQL> SELECT MFR_ID, PRODUCT_ID
  2  FROM PRODUCTS
  3  WHERE PRICE > 500.00
  4  UNION ALL
  5  SELECT DISTINCT MFR, PRODUCT
  6  FROM ORDERS
  7  WHERE AMOUNT > 4.00
  8  ORDER BY 1,2
  9  /

MFR PRODU
--- -----
ACI 4100X
ACI 4100Y
ACI 4100Z
ACI 4100Z
ACI 41002
ACI 41004
BIC 41003
BIC 41003
IMM 773C
IMM 775C
IMM 775C
IMM 779C
IMM 779C
QSA XK47
REI 2A44L
REI 2A44L
REI 2A44R
REI 2A44R
REI 2A45C

19 строк выбрано.

Ух, ты! Сработало! Только имена столбцов не используйте, так как может возникнуть путаница! Лучше их порядковые номера! Вот такие примеры! :) Так же можно писать многократные запросы на обьеденение:

Например:

SELECT * FROM A
	UNION (SELECT * 
		FROM B
		UNION
		SELECT * 
		FROM C)
	        
-------
Вася
Петя
Коля
Маша

4 строки выбрано.

Скобки показывают какой оператор UNION должен выполниться первым. Так же независимо от того исключаются повторяющиеся строки или нет, выражения например такого типа полностью эквивалентны:

A UNION (B UNION C)

(A UNION B) UNION C

(A UNION C) UNION B

Если применять предложение ALL, то следующий тип обьеденения, так же одно и то же!

A UNION ALL (B UNION ALL C)

(A UNION ALL B) UNION ALL C

(A UNION ALL C) UNION ALL B

Если вы применяете и UNION и UNION ALL, то выражение типа:

A UNION ALL B UNION C

Переписать как:

A UNION ALL (B UNION C)
или
(A UNION ALL B) UNION C

То результаты таких запросов будут РАЗЛИЧНЫ!!!

Не путайтесь, в таких случаях и, применяя такие выражения, четко представляйте себе, чего вы хотите получить! Собственно вот такие дела, пробуйте еще раз все самостоятельно и усваивайте материал! :)))


Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Летучий Сергей - 24.08.2003