- •Глава 1. Историческая справка. 10
- •Глава 2. Пример бд «Ресторан». 20
- •Глава 3. Выборка данных. 25
- •Глава 4. Подзапросы и производные таблицы 65
- •Глава 5. Функции ранжирования. 86
- •Глава 1. Историческая справка.
- •Стандарты.
- •1.2. Структура sql.
- •Глава 2. Пример бд «Ресторан».
- •2.1. Описание.
- •2.2. Диаграмма.
- •2.3. Данные в таблицах.
- •Глава 3. Выборка данных.
- •3.1. Оператор select. Синтаксис.
- •3.2. Примеры запросов с использованием единственной таблицы.
- •3.2.1. Выборка без использования фразы where.
- •3.2.1.1. Простейшие примеры.
- •3.2.1.2. Исключение дубликатов (distinct).
- •3.2.1.3. Выборка вычисляемых значений.
- •3.2.2. Выборка c использованием фразы where.
- •3.2.2.1. Использование операторов сравнения.
- •3.2.2.2. Сравнение с null.
- •3.2.2.3. Использование between.
- •3.2.2.4. Использование in (not in).
- •3.2.2.5. Использование like.
- •3.2.2.6. Выборка с упорядочением.
- •3.2.3. Использование агрегатных функций для подведения итогов.
- •3.2.3.1. Агрегатные функции без использования фразы group by.
- •3.2.3.2. Фраза group by.
- •3.2.3.3. Раздел having.
- •3.3. Примеры запросов с использованием нескольких таблиц.
- •3.3.1. Соединения «с условием where».
- •3.3.2. Соединение таблиц с дополнительными условиями.
- •3.3.2.1. Соединение таблицы со своей копией.
- •3.4. Соединения нескольких таблиц, используя join.
- •3.4.1. Внутреннее соединение.
- •3.4.2. Внешнее соединение.
- •3.4.2.1. Левое внешнее соединение.
- •3.4.2.2. Правое внешнее соединение.
- •3.4.2.3. Полное внешнее соединение.
- •3.4.2.4. Перекрёстное соединение.
- •3.4.3. Реальные примеры соединений.
- •Isnull(cast(n.Количество as varchar), ’нет’) as на_складе
- •Isnull(cast(n.Количество as varchar),’нет’) as на_складе
- •Глава 4. Подзапросы и производные таблицы
- •4.1.Производная таблица.
- •4.2. Вложенные подзапросы
- •4.2.1 Простые вложенные подзапросы
- •4.2.2. Использование одной и той же таблицы во внешнем и вложенном подзапросе
- •4.2.3. Использование агрегатных функций в подзапросах.
- •4.2.4. Подзапросы в предложении having.
- •4.3. Соотнесенные подзапросы.
- •4.4 Использование оператора exists.
- •4.5. Использование операторов any и all.
- •4.6. Объединение запросов union.
- •4.6.1. Union и устранение дубликатов.
- •4.6.2. Использование строк и выражений с union.
- •4.6.3. Использование union с order by.
- •4.6.4. Реализация внешнего полного соединения через запросы с union.
- •Глава 5. Функции ранжирования.
- •5.1. Функция row_number.
- •5.2. Функции rank() и dense_rank()
- •Глава 6. ИспользованиеPivoTиUnpivot.
- •In ([Овощи], [Мясо], [Рыба], [Молоко], [Яйца], [Крупа], [Фрукты], [Кофе])
- •In ( [первый сведенный столбец], [второй сведенный столбец],
- •In ([Овощи], [Мясо], [Рыба], [Молоко], [Яйца], [Крупа], [Фрукты], [Кофе])
- •Insert into Продукты (id_Продукта, Продукт, Белки)
- •Values (18, 'Горох', 180 );
- •Insert into Продукты (Продукт, Белки, Жиры)
- •7.4. Оператор update.
- •Глава 8. Представление.
- •Insert into Список_блюд values (36, 'Рагу', 3, 20);
- •Глава 9. Создание, изменение и удаление таблиц.
- •9.1. Оператор create table
- •6. Ограничение identity (автоинкрементное поле).
- •9.2. Изменение таблицы после того как она была создана (alter table).
- •9.3. Удаление таблицы (drop table).
- •9.4. Операторы создания и удаления индексов.
- •9.5. Понятие домена
- •Глава 10. Обобщенные табличные выражения (сте).
- •Представления, производные таблицы и выражения cte.
- •Рекурсивные запросы.
- •Id_father integer foreign key references Tree (id),
- •Values (1, null, 'all'), (2, 1, 'sea'), (3, 1, 'earth'),
- •Деревья без рекурсии.
- •Пример использования сте для решения задачи Коммивояжера.
- •Insert into tur select to_town, from_town, miles from tur;
- •Глава 11. Этапы выполнения командыSql.
- •11.1. Оптимизация запросов.
- •Приложение 1. Реализация реляционной алгебры средствами оператора select (Реляционная полнота sql).
- •Intersect
- •Рекомендуемая литература
Id_father integer foreign key references Tree (id),
NAME VARCHAR(16));
Заполним её данными INSERT INTO Tree
Values (1, null, 'all'), (2, 1, 'sea'), (3, 1, 'earth'),
(4, 1, 'AIR'), (5, 2, 'SUBMARINE'),
(6, 2, 'BOAT'), (7, 3, 'CAR'),
(8, 3, 'TWO WHEELES'), (9, 3, 'TRUCK'),
(10, 4, 'ROCKET'), (11, 4, 'PLANE'),
(12, 8, 'MOTORCYCLE'), (13, 8, 'BYCYCLE');
Обычно иерархия схематизируется авто-ссылкой, которая имеет место и здесь: внешний ключ ссылается на первичный ключ той же таблицы. Имеющиеся данные можно трактовать следующим образом:
ALL |--SEA | |--SUBMARINE | |--BOAT |--EARTH | |--CAR | |--TWO WHEELES | | |--MOTORCYCLE | | |--BYCYCLE | |--TRUCK |--AIR |--ROCKET |--PLANE
Построим запрос. Необходимо узнать, откуда пришел МОТОЦИКЛ (MOTORCYCLE). Другими словами, требуется найти всех предков "МОТОЦИКЛА". Начать следует со строки данных, которая содержат motorcycle:
Результат |
|
NAME |
ID_FATHER |
MOTORCYCLE |
8 |
FROM Tree
WHERE NAME = 'MOTORCYCLE';
Мы должны иметь родительский ID, чтобы перейти к следующему шагу. Второй запрос, который делает этот следующий шаг, должен быть написан подобно следующему:
SELECT NAME, ID_FATHER FROM Tree;
Запросы отличаются только тем, что мы не задаем фильтр WHERE для перехода к следующему шагу. Затем мы должны объединить эти два запроса с помощью UNION ALL, что определит пошаговый метод:
SELECT NAME, ID_FATHER FROM Tree
WHERE NAME = 'MOTORCYCLE'
UNION ALL SELECT NAME, ID_FATHER FROM Tree;
Теперь разместим все это в CTE:
WITH
tree_CTE (data, id)
AS (SELECT NAME, ID_FATHER
FROM Tree
WHERE NAME = 'MOTORCYCLE'
UNION ALL SELECT NAME, ID_FATHER FROM Tree
);
Теперь мы вплотную подошли к рекурсии. Последний шаг должен сделать цикл, чтобы организовать выполнение пошагового метода. Это делается при использовании имени CTE в качестве таблицы внутри SQL-запроса CTE. В нашем случае мы должны соединить второй запрос CTE с самим CTE, организовав цепочку по tree_CTE.id = (второй запрос).ID. Это можно сделать следующим образом:
WITH
tree_CTE (data, id)
AS (SELECT NAME, ID_FATHER
FROM Tree
WHERE NAME = 'MOTORCYCLE'
UNION ALL SELECT NAME, ID_FATHER FROM Tree JOIN tree_CTE ON tree_CTE.id = Tree.ID
)
Результат |
|
data |
id |
MOTORCYCLE |
8 |
TWO WHEELES |
3 |
EARTH |
1 |
ALL |
NULL |
Что остановило рекурсивный процесс? Факт, что больше нет звеньев цепочки, когда достигается значение id "NULL", что в нашем примере означает случай достижения "ALL".
Отметим, что по неясным причинам MS SQL Server 2005 не допускает ключевого слова RECURSIVE после слова WITH, которое вводит CTE.
Еще одна важная вещь, связанная со структурированными в форме деревьев данными, - это визуализация данных в виде дерева ..., что означает наличие отступов в иерархии при извлечении данных. Возможно ли это? Да, конечно. Это может быть сделано вычислением пути внутри рекурсии и уровня вложенности. Вот пример такого запроса:
WITH tree_CTE (data, id, level, pathstr)
AS (SELECT NAME, ID, 0, cast(' ' as varchar(MAX))
FROM Tree
WHERE ID_FATHER IS NULL
UNION ALL SELECT NAME, Tree.ID,
tree_CTE.level+4, tree_CTE .pathstr + ' ' +Tree.NAME
FROM Tree JOIN tree_CTE ON tree_CTE.id = Tree. ID_FATHER
)
SELECT SPACE(level) + data as data, id, level, pathstr FROM tree_CTE;
Результат |
| ||
data |
id |
level |
pathstr |
ALL |
1 |
0 |
|
SEA |
2 |
4 |
SEA |
EARTH |
3 |
4 |
EARTH |
AIR |
4 |
4 |
AIR |
ROCKET |
10 |
8 |
AIR ROCKET |
PLANE |
11 |
8 |
AIR PLANE |
CAR |
7 |
8 |
EARTH CAR |
TWO WHEELES |
8 |
8 |
EARTH TWO WHEELES |
TRUCK |
9 |
8 |
EARTH TRUCK |
MOTORCYCLE |
12 |
12 |
EARTH TWO WHEELES MOTORCYCLE |
BYCYCLE |
13 |
12 |
EARTH TWO WHEELES BYCYCLE |
SUBMARINE |
5 |
8 |
SEA SUBMARINE |
BOAT |
6 |
8 |
SEA BOAT |
Мы использовали новый тип данных в SQL 2005, который называется VARCHAR (MAX), поскольку мы не знаем максимального количества символов, которое потребуется при конкатенации VARCHAR (16) в рекурсивном запросе, который может оказаться очень глубоким.