Оператор SELECT . |
Весь запрос SELECT разбивается на отдельные разделы, каждый из которых имеет своё назначение. Большая часть этих разделов может быть опущена. Упрощённый вариант синтаксиса оператора SELECT : 1 SELECT [ALL | DISTINCT] < список вывода > 2 [ INTO <имя новой таблицы> ] 3 FROM <список таблиц и условий соединения> 4 [ WHERE <условие отбора или соединения> ] 5 [ GROUP BY <список полей группировки> ] 6 [ HAVING <условия, накладываемые на группу> ] 7 [ ORDER BY <список полей для сортировки вывода> ] 8 [ UNION <запрос на выборку для объединения>] 9 … <список вывода>::= { * | [<имя таблицы> | <алиас>.] {<имя столбца> | <выражение>} [ AS <алиас>] | <имя столбца> = <выражение> } [… n ] Символ звёздочка означает, что в результирующий набор включаются все столбцы из указанных исходных таблиц: SELECT * FROM publishers Декартово произведение отношений: SELECT * FROM publishers, authors ALL – в результирующий набор включаются все строки, удовлетворяющие условиям запроса, даже если среди них будут одинаковые (?!, то есть полученное отношение не удовлетворяет требованиям реляционной алгебры). SELECT ALL p.country FROM publishers AS p DISTINCT – в результирующий набор включаются только уникальные строки. Если в результат выборки включаются несколько столбцов, то уникальность будет определяться по значениям обоих этих столбцов. SELECT DISTINCT state, contract FROM authors Простейшие вычисления в разделе SELECT: SELECT ' Название книги : ', title, yearpub-1992 FROM titles WHERE yearpub > 1992; Раздел WHERE предназначен для наложения горизонтальных фильтров на данные, обрабатываемые запросом. Для этого указывается логическое условие, от результата вычисления которого зависит, будет ли строка включена в результат выборки или нет. SELECT au_lname, au_fname, state FROM authors WHERE state<>'CA' Предикаты, используемые в условных конструкциях SQL : 1) Предикаты сравнения: = , <> , < , > , >= , <= ; SELECT * FROM authors WHERE 1=1 2) AND – соединение нескольких логических выражений; SELECT title FROM titles WHERE yearpub>=1995 AND yearpub<=1997 3) OR – если одно из двух условий истинно, то результат True ; SELECT title FROM titles WHERE yearpub<1995 OR yearpub>1997 4) NOT – отрицание, может ставиться непосредственно перед нижеследующими предикатами; 5) Предикат диапазона: Between A and B – принимает значение True , если сравниваемое значение лежит между A и В; SELECT title FROM titles WHERE yearpub NOT BETWEEN 1995 AND 1997 6) Вхождение во множество: IN (<список значений>) – принимает True , если сравниваемое значение входит во множество заданных значений; SELECT title FROM titles WHERE yearpub IN (1995, 1996, 1997) 7) Сравнение с образцом: LIKE . В шаблон могут входить специальные символы « _ » – для обозначения любого одиночного символа, и « % » – для обозначения произвольной последовательности символов; SELECT publisher, url FROM publishers WHERE publisher LIKE ‘%Wiley%' 8) Предикат сравнения с неопределённым значением: IS NULL . SELECT publisher, “url not defined !” FROM publishers WHERE url IS NULL Связь между таблицами с использованием раздела WHERE (стандарт SQL 89) Представим ситуацию, когда выборку данных надо производить из отношения, которое является результатом слияния нескольких отношений. При отсутствии соединения в разделе WHERE результат будет эквивалентен расширенному декартовому произведению отношений. Обычно всегда в случае использования нескольких таблиц имени поля предшествует имя таблицы во всех разделах оператора SELECT . SELECT titles.title, titles.yearpub, publishers.publisher FROM titles, publishers WHERE titles.pub_id = publishers.pub_id AND titles.yearpub>1996 В данном запросе в разделе WHERE указаны условия связи и условия фильтрации данных. Связь между таблицами с использованием раздела FROM (стандарт SQL 2, внешние объединения) С помощью раздела FROM определяются источники данных, с которыми будет работать запрос. Связи между отношениями в этом разделе реализуются как одна или несколько вложенных связей между левой и правой таблицами по одному или нескольким полям.
Пример связи двух таблиц: SELECT authors.au_lname, authors.au_fname, titleauthor.royalty FROM authors INNER JOIN titleauthor ON authors.au_id = titleauthor.au_id WHERE authors.state='CA' Если бы мы хотели узреть и тех авторов из штата Калифорния, которые не получили гонорар, то надо было бы использовать конструкцию LEFT JOIN Пример связи нескольких таблиц: SELECT countries.name_rus AS страна , subjects.name_rus AS регион , msu.name_rus AS район , data.year AS год FROM data INNER JOIN subjects ON data.subject = subjects.subject INNER JOIN msu ON data.msu = msu.id_msu INNER JOIN countries ON subjects.country = countries.country Раздел GROUP BY позволяет выполнять группировку строк таблиц по определённым критериям. Типичным примером использования GROUP BY является суммирование однотипных значений. GROUP BY почти всегда используется вместе с функциями агрегирования. GROUP BY разделяет таблицу на группы, а функция агрегирования вычисляет для каждой из них итоговое значение. Основные функции агрегирования:
Следующий запрос определяет количество книг каждого издательства, зарегистрированных в базе данных: SELECT publishers.publisher, COUNT(titles.title) FROM titles, publishers WHERE titles.pub_id = publishers.pub_id GROUP BY publisher Правила использования группировок в запросах: 1) Функции агрегирования не работают со значениями NULL . 2) В разделе SELECT (т.е. для вывода) можно указывать только те поля, по которым осуществляется группировка. Чтобы вывести значения столбцов, не указанных в критериях группировки, необходимо применять к ним функции агрегирования. 3) Раздел WHERE не допускает использования функций агрегирования. Ещё один пример: подсчитать, сколько записей ввёл каждый из операторов по каждому региону за 2003 год. SELECT max(subjects.name_rus) as [ субъект ], COUNT(*) AS [ количество записей ], max(users.u_name) as [ оператор ] FROM subjects, data, users WHERE data.subject = subjects.subject and data.id_user = users.id_user and data.year=2003 GROUP BY data.subject, data.id_user ORDER BY [ субъект ] Если при выполнении группировки используется раздел WHERE , то возможно появление групп, не содержащих ни одной строки. По умолчанию эти группы не включаются в результат выборки. Однако если необходимо вывести все без исключения группы, то используется вариант GROUP BY ALL . При этом для групп, не содержащих ни одной строки, не выполняются функции агрегирования, вместо которых выводится значение NULL . Простой запрос, использующий функцию агрегирования без группировки: SELECT Count(*) FROM data Раздел HAVING . Этот раздел практически аналогичен по назначению с разделом WHERE (горизонтальная фильтрация), однако используется для задания условий групповой фильтрации. В этом разделе допускается использование функций агрегирования. Определим количество книг каждого издательства, исключая случаи единственного экземпляра. SELECT publishers.publisher, COUNT(titles.title) FROM titles, publishers WHERE titles.pub_id = publishers.pub_id GROUP BY publisher HAVING COUNT (*)>1; Другой пример: получить номера деталей, суммарное количество которых на складе превышает 400 шт. SELECT number, SUM(volume) FROM warehouse GROUP BY number HAVING SUM(volume)>400 Раздел ORDER BY предназначен для упорядочения набора данных, возвращаемых после выполнения запроса. Используются ключевые слова ASC (по возрастанию, используется по умолчанию) и DESC (по убыванию). При этом в сортировке могут участвовать столбцы, не входящие в раздел SELECT . Приоритет в сортировке по столбцам, указанным первыми. SELECT data.* FROM data ORDER BY subject, msu, year Раздел UNION служит для объединения результатов выборки, возвращаемых двумя и более запросами. Это может быть выборка из одной таблицы или слияние данных из множества таблиц. Иными словами, раздел UNION вставляется между двумя запросами, возвращающими одинаковый набор столбцов. В результат будут включены строки как первого, так и второго запроса. По умолчанию дублирующие строки в результат не включаются. SELECT publisher, url FROM publishers UNION SELECT site , url FROM wwwsites Использование вложенных запросов. Команда SELECT позволяет использовать подзапросы в предикатах главного (т.е. в разделах WHERE и HAVING ). Совместно с подзапросом можно использовать предикат EXIST , который возвращает истину, если вывод подзапроса не пуст. Задача: найти названия всех изданий, выпущенные издательством « Wiley » SELECT title FROM titles WHERE pub_id IN (SELECT pub_id FROM publishers WHERE publisher='Wiley'); Более сложные задачи: даны отношения Supplier s ( id _ supplier , name ) – поставщики (код поставщика, ФИО поставщика) Supply ( id _ supplier , number ) – поставки (код поставщика, номер детали) Components ( number , title ) – детали (номер детали, наименование детали). 1. Найти имена поставщиков, которые поставляют все детали из занесённых в базу. SELECT MAX(suppliers.name) FROM suppliers, supply WHERE suppliers.id_supplier=supply.id_supplier GROUP BY supply.id_supplier HAVING COUNT( DISTINCT supply.number) = ( SELECT COUNT(number) FROM components) 2. Получить список поставщиков, поставляющих деталь с номером 222. SELECT * FROM suppliers WHERE EXIST (SELECT * FROM supply WHERE suppliers.id_supplier = supply.id_supplier AND supply.number = 222); Такие подзапросы называются коррелируемыми ( correlated ). Внешняя ссылка может принимать различные значения для каждой строки-кандидата, оцениваемого с помощью подзапроса, поэтому подзапрос должен выполняться заново для каждой строки, отбираемой в основном запросе. Простой пример: контроль ссылочной целостности вручную: SELECT * FROM data WHERE item NOT IN (SELECT item FROM items) Реализация реляционной алгебры средствами оператора SELECT (Реляционная полнота SQL ) Для того, чтобы показать, что язык SQL является реляционно полным, нужно показать, что любой реляционный оператор может быть выражен средствами SQL .
|