![](/user_photo/2706_HbeT2.jpg)
- •Оглавление Извлечение данных. Оператор select
- •Оператор select
- •Предикаты (часть I)
- •Предикаты сравнения
- •Предикат between
- •Предикат in
- •Переименование столбцов и вычисления в результирующем наборе
- •Предикаты (часть 2) Предикат like
- •Использование значения null в условиях поиска Предикат is [not] null
- •Получение итоговых значений
- •Предложение group by
- •Предложение having
- •Использование в запросе нескольких источников записей
- •Явные операции соединения
- •Традиционные операции над множествами и оператор select
- •Декартово произведение
- •Объединение
- •Пересечение и разность
- •Предикат exists
- •Использование ключевых слов some | any и all с предикатами сравнения
- •Еще о подзапросах
- •Преобразование типов
- •Оператор case
- •Функции Transact-sql для обработки даты/времени
- •Функция dateadd
- •Функция datediff
- •Функция datepart
- •Функция datename
- •Функции работы со строками в ms sql server 2005
- •Функция substring
- •Функция reverse
- •Функция replace
- •Функции ltrim и rtrim
- •Функции lower и upper
- •Функция unicode
- •Функция nchar
- •Операторы модификации данных
- •Оператор insert
- •Вставка строк в таблицу, содержащую автоинкрементируемое поле
- •Оператор update
- •Оператор delete
- •Приложение 1. Описание учебных баз данных
- •1. Компьютерная фирма
- •2. Фирма вторсырья
- •3. Корабли
- •4. Аэрофлот
- •5. Окраска
- •Приложение 2. Список упражнений (select)
- •Как объединить данные из двух столбцов в один без использования union и join?
- •1. Union all
- •2. Full join
- •3. Unpivot
- •Комментарии
- •Как добавить новый столбец в таблицу между существующими столбцами?
- •Как вывести по n строк из каждой группы?
- •"Классическое" решение
- •1. Соединение
- •2. Подзапрос в предложении select
- •Решение на основе ранжирующих функций
- •Как удалить дубликаты строк из таблицы?
- •1. Нумерация строк
- •2. Ранжирование строк внутри групп дубликатов
- •3. Удаление дубликатов из виртуальной таблицы
- •Как удалить дубликаты строк при наличии первичного ключа?
- •Id name
- •Id_pk color
- •Id name color
- •Обновление таблицы t_details
- •Id_pk name color dup min_id
- •Id_pk color
- •Id name
- •Id_pk color
Предложение having
Если предложение WHERE определяет предикат для фильтрации строк, то предложение HAVING применяется после группировки для определения аналогичного предиката, фильтрующего группы по значениям агрегатных функций. Это предложение необходимо для проверки значений, которые получены с помощью агрегатной функции не из отдельных строк источника записей, определенного в предложении FROM, а из групп таких строк. Поэтому такая проверка не может содержаться в предложении WHERE.
Пример. Получить количество ПК и среднюю цену для каждой модели при условии, что средняя цена менее $800:
SELECT model, COUNT(model) AS Qty_model, AVG(price) AS Avg_price FROM PC GROUP BY model HAVING AVG(price) < 800; |
В результате выполнения запроса получим:
model |
Qty_model |
Avg_price |
1232 |
4 |
425.0 |
1260 |
1 |
350.0 |
Заметим, что в предложении HAVING нельзя использовать псевдоним (Avg_price), используемый для именования значений агрегатной функции. Дело в том, что предложение SELECT, формирующее выходной набор запроса, выполняется предпоследним перед предложением ORDER BY.
Ниже приведен порядок обработки предложений в операторе SELECT:
FROM
WHERE
GROUP BY
HAVING
SELECT
ORDER BY
Этот порядок не соответствует синтаксическому порядку общего формата оператора SELECT, представленному ниже:
SELECT [DISTINCT | ALL]{* | [<выражение для столбца> [[AS] <псевдоним>]] [,…]} FROM <имя таблицы> [[AS] <псевдоним>] [,…] [WHERE <предикат>] [[GROUP BY <список столбцов>] [HAVING <условие на агрегатные значения>] ] [ORDER BY <список столбцов>]
Рекомендуемые упражнения: 10, 11, 12, 14, 15, 20, 22, 33, 43, 51, 52.
Использование в запросе нескольких источников записей
Как видно из приведенного в конце предыдущего раздела синтаксиса оператора SELECT, в предложении FROM допускается указание нескольких таблиц. Простое перечисление таблиц практически не используется, поскольку оно соответствует реляционной операции декартова произведения. Т.е. в результирующем наборе каждая запись из одной таблицы будет сочетаться с каждой записью в другой. Например, для таблиц
A |
|
B | ||
a |
b |
|
c |
d |
1 |
2 |
|
2 |
4 |
2 |
1 |
|
3 |
3 |
Результат запроса
SELECT * FROM A, B; |
будет выглядеть следующим образом:
a |
b |
c |
d |
1 |
2 |
2 |
4 |
1 |
2 |
3 |
3 |
2 |
1 |
2 |
4 |
2 |
1 |
3 |
3 |
Поэтому перечисление таблиц, как правило, используется совместно с условием соединения записей из разных таблиц, указываемым в предложении WHERE. Для приведенных выше таблиц таким условием может быть совпадение значений, скажем, в полях a и c:
SELECT * FROM A, B WHERE a=c; |
Теперь результатом выполнения этого запроса будет следующая таблица:
a |
b |
c |
d |
2 |
1 |
2 |
4 |
т.е. соединяются только те строки таблиц, у которых в указанных полях находятся равные значения (эквисоединение). Естественно, могут быть использованы любые условия, хотя эквисоединение используется чаще всего, поскольку эта операция воссоздает некую сущность, декомпозированную на две других в результате процедуры нормализации.
Если разные таблицы имеют столбцы с одинаковыми именами, то для однозначности требуется использовать точечную нотацию:
<имя таблицы>.<имя поля>
В тех случаях, когда это не вызывает неоднозначности, использование данной нотации не является обязательным.
Пример. Найти номер модели и производителя ПК, имеющих цену менее $600:
SELECT DISTINCT PC.model, maker FROM PC, Product WHERE PC.model = Product.model AND price < 600; |
В результате каждая модель одного и того же производителя выводится только один раз:
model |
maker |
1232 |
A |
1260 |
E |
Иногда в предложении FROM требуется указать одну и ту же таблицу несколько раз. В этом случае обязательным является переименование.
Пример. Вывести пары моделей, имеющих одинаковые цены:
SELECT DISTINCT A.model AS model_1, B.model AS model_2 FROM PC AS A, PC B WHERE A.price = B.price AND A.model < B.model; |
Здесь условие A.model < B.model используется для того, чтобы не выводились одинаковые пары, отличающиеся только перестановкой, например: 1232, 1233 и 1233, 1232. DISTINCT применяется для того, чтобы исключить одинаковые строки, поскольку в таблице PC имеются одинаковые модели по одной и той же цене. В результате получим следующую таблицу:
model_1 |
model_2 |
1232 |
1233 |
1232 |
1260 |
Переименование также требуется, если в предложении FROM используется подзапрос. Так, первый пример можно переписать следующим образом:
SELECT DISTINCT PC.model, maker FROM PC, (SELECT maker, model FROM Product) AS prod WHERE PC.model = prod.model AND price < 600; |
Обратите внимание, что в этом случае в других предложениях оператора SELECT уже нельзя использовать квалификатор Product, поскольку таблица Product уже не используется. Вместо него используется псевдоним prod. Кроме того, ссылаться теперь можно только на те поля таблицы Product, которые перечислены в подзапросе.