
- •Лабораторная работа «Оператор select»
- •Предложение having - наложение ограничений на группировку записей
- •Использование between
- •Использование in (список значений)
- •Использование starting
- •Использование containing
- •Использование функции upper
- •Использование like
- •Использование функции cast
- •Использование подзапросов
- •Дополнительные возможности использования подзапросов, возвращающих единичное значение Использование exists
- •Использование singular
- •Использование подзапросов, возвращающих множество значений Использование all, some
- •Использование having и агрегатных функций для вложенных подзапросов
- •Внешние соединения
- •Union - объединение результатов выполнения нескольких операторов select
- •Использование is null
- •Использование операции сцепления строк
- •Работа с разными бд в одном запросе
Использование функции cast
Иногда возникает потребность трактовать значение одного типа как значение другого типа. Например, использовать числовое значение как символьную строку или наоборот. В этом случае применяют функцию
CAST (<значение> AS <тип данных>)
Функция CAST делает копию значения, преобразуя его к указанному типу данных. При этом не следует забывать о множестве типов данных, в которое может быть преобразовано данное значение:
Пример. Найти покупателя, который делал закупки то ли на 209, то ли на 309 единиц товара. На сколько именно, никто не помнит; вспомнили лишь, что последними разрядами в количестве отпускаемого товара были цифры '09'. Тогда приводим значения столбца KOLVO к типу CHARACTER и к результату применяем LIKE
Пример. Выдать все покупки товара за 20 число (предположим, каждого месяца). В InterBase нет встроенных функций для разделения даты на число, месяц и год. Варианты решения:
• в приложении, разработанном на Delphi, анализировать даты при помощи процедуры DecodeDate;
• написать UDF (User Defined Function, определенную пользователем функцию), которая реализует выделение номера дня из даты, и использовать имя этой функции в операторе SELECT;
• привести значение даты к типу CHAR (или, что лучше, трактовать значение даты как строковое значение) и применить к полученному значению LIKE, CONTAINING или STARTING WITH, в зависимости от потребности.
Воспользуемся последним способом:
SELECT DAT_RASH, TOVAR, POKUP, KOLVO FROM RASHOD .
WHERE CAST(DAT_RASH AS CHAR(6)) STARTING WITH "20"
ЗАМЕЧАНИЕ. Значение типа DATE не нужно приводить к строковому типу, поскольку два этих типа являются совместимыми и значение DATE в InterBase может трактоваться как строковое, следовательно в данном примере можно устранить ненужное приведение типов:
SELECT DAT_RASH, TOVAR, POKUP, KOLVO
FROM RASHOD WHERE DAT_RASH STARTING WITH "20"
(Предполагается, что формат задания даты – день.месяц.год)
Использование подзапросов
Часто невозможно решить поставленную задачу путем использования одного запроса. Это особенно актуально в тех случаях, когда при использовании условия поиска в предложении WHERE
Сравниваемое значение> <оператор> <значение, с которым сравнивать>
значение, с которым надо сравнивать, заранее не определено и должно быть вычислено в момент выполнения оператора SELECT. Другой причиной использования вложенных подзапросов, является то, что во многих случаях значение, с которым надо сравнивать, должно представлять собой не одно, а несколько значений.
В общем случае оператор SELECT с подзапросом имеет вид
SELECT .. .
FROM ...
WHERE Сравниваемое значение> <оператор> (SELECT ... FROM ... WHERE ... )
Пример. Выдать все даты, на которые приходится максимальный отпуск товаров
SELECT KOLVO, DAT_RASH FROM RASHOD
WHERE KOLVO = (SELECT MAX(KOLVO) FROM RASHOD)
Сначала будет найдено максимальное количество отпуска товаров, поскольку это значение заранее неизвестно. Это и делает внутренний подзапрос.
Далее выполняется основной запрос.
Пример. Усложним предыдущий пример. Определить дату, когда со склада было отгружено максимальное количество товара, и реквизиты покупателя, который этот товар купил
SELECT R.KOLVO, R.DAT_RASH, P.POKUP, P.GOROD, P.ADRES
FROM RASHOD R, POKUPATELI P
WHERE (R.POKUP = P.POKUP) AND
KOLVO =(SELECT MAX(KOLVO) FROM RASHOD)
По сравнению с предыдущим примером в запрос включено внутреннее соединение таблиц RASHOD и POKUPATELI.
Пример. Составить список отгрузки товаров покупателю, который в свое время купил максимальную партию какого-либо товара
SELECT RRR.* FROM RASHOD RRR
WHERE RRR.POKUP IN (SELECT R.POKUP FROM RASHOD R
WHERE KOLVO = (SELECT MAX(RSH.KOLVO) FROM RASHOD RSH))
ЗАМЕЧАНИЕ. IN использован вместо знака равенства на тот случай, если встретится два и более покупателя, имеющие одинаковое число максимальных покупок. В этом случае запрос вернет записи из RASHOD по всем таким покупателям.
Логический порядок выполнения запроса. Вычисляется максимальное значение в столбце KOLVO ("самый вложенный" подзапрос SELECT MAX). Далее в "среднем" подзапросе SELECT R.POKUP выбирается покупатель, купивший какой-либо товар в количестве, равном значению, вычисленному в "самом вложенном" подзапросе. Вслед за этим "самый главный" запрос SELECT RRR выбирает записи с покупателем, наименование которого выдано "средним" подзапросом.
ЗАМЕЧАНИЕ. Поставленную задачу могут выполнить и другие запросы, например:
SELECT RRR.* FROM RASHOD RRR WHERE RRR.POKUP IN
(SELECT R.POKUP FROM RASHOD R GROUP BY R.POKUP
HAVING MAX(R.KOLVO) = (SELECT MAX(RSH.KOLVO) FROM RASHOD RSH))