2.13. Объединение запросов

Допустим, что есть какая-то задача, которую вы не можете решить в один запрос. Например, допустим, что нужно выбрать из таблицы все записи, в которых в поле "vcName" указано имя Андрей, а в поле "vcSurName" указана фамилия Васильевич. При этом, если запись удовлетворяет и тому и другому условию, то она должна быть выведена в результате дважды. Как решить эту задачу? Если написать запрос:

SELECT vcFamil, vcName, vcSurName
FROM tbPeoples
WHERE vcName='Андрей' 
  OR vcSurName='Васильевич'

То оба условия будут описаны верно, но в результате человек с именем и отчеством Андрей Васильевич попадет в результат только один раз, а нам надо два.

Проблема решается выполнением двух запросов. Сначала необходимо определить все записи с именем Андрей, а потом с отчеством Васильевич. Но это будет два набора результата. Как их объединить в один? Для этого между запросами нужно написать один из следующих операторов:

  • UNION – объединить результат, и если есть строки, одинаковые для обоих результатов, то вывести только одну строку.
  • UNION ALL – объединить результат и включить в него все строки, даже повторяющиеся в обоих наборах.

Для решения нашей задачи нужно использовать UNION ALL, чтобы ни одна строка не исчезла и если какая-то запись соответствует двум условиям, она должна попадать в результат дважды:

SELECT vcFamil, vcName, vcSurName
FROM tbPeoples
WHERE vcName='Андрей'

UNION ALL

SELECT vcFamil, vcName, vcSurName
FROM tbPeoples
WHERE vcSurName='Васильевич'

Как видите, это всего лишь два запроса, между которыми стоит ключевое слово UNION ALL. У объединения есть одно ограничение – сортировку надо указывать только во втором запросе. Если поставить оператор ORDER BY в первом запросе, то в результате вы получите ошибку. А если указать во втором, то сортироваться будет весь результат (обоих запросов) как одно целое.

Чтобы в результирующем наборе было видно, какая запись была получена первым запросом, а какая вторым, давайте добавим еще одну колонку к каждому из запросов, в которой будет отображаться текст с номером запроса:

SELECT vcFamil, vcName, vcSurName, 'Запрос 1'
FROM tbPeoples
WHERE vcName='Андрей'

UNION ALL

SELECT vcFamil, vcName, vcSurName, 'Запрос 2'
FROM tbPeoples
WHERE vcSurName='Васильевич'

Не все так красиво у оператора UNION. У него есть следующие ограничения в использовании:

  • Количество и типы полей должны быть одинаковыми.
  • Символьные поля должны иметь одинаковое число символов.

Подобные запросы очень эффективны, когда нужно обращаться к разным базам данных. Например, один запрос выбирает данные из базы данных Database1, а другой из Database2.

Если одного поля в одном из запросов нет, то его можно заменить. Например, допустим, что во втором запросе происходит обращение к таблице, в которой нет поля фамилии. Да, у нас обращение идет к одной и той же таблице, но мы просто представим такую ситуацию. Как можно решить проблему? Вместо поля можно указать какой-либо текст, например:

SELECT vcFamil, vcName, vcSurName, 'Запрос 1'
FROM tbPeoples
WHERE vcName='Андрей'

UNION ALL

SELECT 'Не найдено', vcName, vcSurName, 'Запрос 2'
FROM tbPeoples
WHERE vcSurName='Васильевич'
ORDER BY vcFamil

В данном примере, во втором запросе вместо поля фамилии указывается текст 'Не найдено'. Для числового поля, вместо не существующего поля, конечно же, нужно указать число.

Предыдущая глава

2.12. Группировка – Group By

Следующая глава

2.14. Подзапросы

О блоге

Программист, автор нескольких книг серии глазами хакера и просто блогер. Интересуюсь безопасностью, хотя хакером себя не считаю

Обратная связь

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

Пишите мне