+ [Какие существуют операторы SQL?](#Какие-существуют-операторы-sql)
+ [Что означает `NULL` в SQL?](#Что-означает-null-в-sql)
+ [Что такое _«временная таблица»_? Для чего она используется?](#Что-такое-временная-таблица-Для-чего-она-используется)
+ [Что такое _«представление» (view)_ и для чего оно применяется?](#Что-такое-представление-view-и-для-чего-оно-применяется)
+ [Каков общий синтаксис оператора `SELECT`?](#Каков-общий-синтаксис-оператора-select)
+ [Что такое `JOIN`?](#Что-такое-join)
+ [Какие существуют типы `JOIN`?](#Какие-существуют-типы-join)
+ [Что лучше использовать `JOIN` или подзапросы?](#Что-лучше-использовать-join-или-подзапросы)
+ [Для чего используется оператор `HAVING`?](#Для-чего-используется-оператор-having)
+ [В чем различие между операторами `HAVING` и `WHERE`?](#В-чем-различие-между-операторами-having-и-where)
+ [Для чего используется оператор `ORDER BY`?](#Для-чего-используется-оператор-order-by)
+ [Для чего используется оператор `GROUP BY`?](#Для-чего-используется-оператор-group-by)
+ [Как `GROUP BY` обрабатывает значение `NULL`?](#Как-group-by-обрабатывает-значение-null)
+ [В чем разница между операторами `GROUP BY` и `DISTINCT`?](#В-чем-разница-между-операторами-group-by-и-distinct)
+ [Перечислите основные агрегатные функции.](#Перечислите-основные-агрегатные-функции)
+ [В чем разница между `COUNT(*)` и `COUNT({column})`?](#В-чем-разница-между-count-и-countcolumn)
+ [Что делает оператор `EXISTS`?](#Что-делает-оператор-exists)
+ [Для чего используются операторы `IN`, `BETWEEN`, `LIKE`?](#Для-чего-используются-операторы-in-between-like)
+ [Для чего применяется ключевое слово `UNION`?](#Для-чего-применяется-ключевое-слово-union)
+ [Какие ограничения на целостность данных существуют в SQL?](#Какие-ограничения-на-целостность-данных-существуют-в-sql)
+ [Какие отличия между ограничениями `PRIMARY` и `UNIQUE`?](#Какие-отличия-между-ограничениями-primary-и-unique)
+ [Может ли значение в столбце, на который наложено ограничение `FOREIGN KEY`, равняться `NULL`?](#Может-ли-значение-в-столбце-на-который-наложено-ограничение-foreign-key-равняться-null)
+ [Как создать индекс?](#Как-создать-индекс)
+ [Что делает оператор `MERGE`?](#Что-делает-оператор-merge)
+ [В чем отличие между операторами `DELETE` и `TRUNCATE`?](#В-чем-отличие-между-операторами-delete-и-truncate)
+ [Что такое _«хранимая процедура»_?](#Что-такое-хранимая-процедура)
+ [Что такое _«триггер»_?](#Что-такое-триггер)
+ [Что такое _«курсор»_?](#Что-такое-курсор)
+ [Опишите разницу типов данных `DATETIME` и `TIMESTAMP`.](#Опишите-разницу-типов-данных-datetime-и-timestamp)
+ [Для каких числовых типов недопустимо использовать операции сложения/вычитания?](#Для-каких-числовых-типов-недопустимо-использовать-операции-сложениявычитания)
+ [Какое назначение у операторов `PIVOT` и `UNPIVOT` в Transact-SQL?](#Какое-назначение-у-операторов-pivot-и-unpivot-в-transact-sql)
+ [Расскажите об основных функциях ранжирования в Transact-SQL.](#Расскажите-об-основных-функциях-ранжирования-в-transact-sql)
+ [Для чего используются операторы `INTERSECT`, `EXCEPT` в Transact-SQL?](#Для-чего-используются-операторы-intersect-except-в-transact-sql)
SQL, Structured query language («язык структурированных запросов») — формальный непроцедурный язык программирования, применяемый для создания, модификации и управления данными в произвольной реляционной базе данных, управляемой соответствующей системой управления базами данных (СУБД).
`NULL` - специальное значение (псевдозначение), которое может быть записано в поле таблицы базы данных. NULL соответствует понятию «пустое поле», то есть «поле, не содержащее никакого значения».
`NULL` означает отсутствие, неизвестность информации. Значение `NULL` не является значением в полном смысле слова: по определению оно означает отсутствие значения и не принадлежит ни одному типу данных. Поэтому `NULL` не равно ни логическому значению `FALSE`, ни _пустой строке_, ни `0`. При сравнении `NULL`с любым значением будет получен результат `NULL`, а не `FALSE` и не `0`. Более того, `NULL` не равно `NULL`!
__Временная таблица__ - это объект базы данных, который хранится и управляется системой базы данных на временной основе. Они могут быть локальными или глобальными. Используется для сохранения результатов вызова хранимой процедуры, уменьшение числа строк при соединениях, агрегирование данных из различных источников или как замена курсоров и параметризованных представлений.
__Представление__, View - виртуальная таблица, представляющая данные одной или более таблиц альтернативным образом.
В действительности представление – всего лишь результат выполнения оператора `SELECT`, который хранится в структуре памяти, напоминающей SQL таблицу. Они работают в запросах и операторах DML точно также как и основные таблицы, но не содержат никаких собственных данных. Представления значительно расширяют возможности управления данными. Это способ дать публичный доступ к некоторой (но не всей) информации в таблице.
__JOIN__ - оператор языка SQL, который является реализацией операции соединения реляционной алгебры. Предназначен для обеспечения выборки данных из двух таблиц и включения этих данных в один результирующий набор.
Особенностями операции соединения являются следующее:
+ в схему таблицы-результата входят столбцы обеих исходных таблиц (таблиц-операндов), то есть схема результата является «сцеплением» схем операндов;
+ каждая строка таблицы-результата является «сцеплением» строки из одной таблицы-операнда со строкой второй таблицы-операнда;
+ при необходимости соединения не двух, а нескольких таблиц, операция соединения применяется несколько раз (последовательно).
Результатом объединения таблиц являются записи, общие для левой и правой таблиц. Порядок таблиц для оператора не важен, поскольку оператор является симметричным.
__LEFT (OUTER) JOIN__
Производит выбор всех записей первой таблицы и соответствующих им записей второй таблицы. Если записи во второй таблице не найдены, то вместо них подставляется пустой результат (`NULL`). Порядок таблиц для оператора важен, поскольку оператор не является симметричным.
__RIGHT (OUTER) JOIN__
`LEFT JOIN`с операндами, расставленными в обратном порядке. Порядок таблиц для оператора важен, поскольку оператор не является симметричным.
__FULL (OUTER) JOIN__
Результатом объединения таблиц являются все записи, которые присутствуют в таблицах. Порядок таблиц для оператора не важен, поскольку оператор является симметричным.
__CROSS JOIN (декартово произведение)__
При выборе каждая строка одной таблицы объединяется с каждой строкой второй таблицы, давая тем самым все возможные сочетания строк двух таблиц. Порядок таблиц для оператора не важен, поскольку оператор является симметричным.
Обычно лучше использовать `JOIN`, поскольку в большинстве случаев он более понятен и лучше оптимизируется СУБД (но 100% этого гарантировать нельзя). Так же `JOIN` имеет заметное преимущество над подзапросами в случае, когда список выбора `SELECT` содержит столбцы более чем из одной таблицы.
Подзапросы лучше использовать в случаях, когда нужно вычислять агрегатные значения и использовать их для сравнений во внешних запросах.
__ORDER BY__ упорядочивает вывод запроса согласно значениям в том или ином количестве выбранных столбцов. Многочисленные столбцы упорядочиваются один внутри другого. Возможно определять возрастание `ASC` или убывание `DESC` для каждого столбца. По умолчанию установлено - возрастание.
`DISTINCT` указывает, что для вычислений используются только уникальные значения столбца. `NULL` считается как отдельное значение.
`GROUP BY` создает отдельную группу для всех возможных значений (включая значение `NULL`).
Если нужно удалить только дубликаты лучше использовать `DISTINCT`, `GROUP BY` лучше использовать для определения групп записей, к которым могут применяться агрегатные функции.
`COUNT (*)` подсчитывает количество записей в таблице, не игнорируя значение NULL, поскольку эта функция оперирует записями, а не столбцами.
`COUNT ({column})` подсчитывает количество значений в `{column}`. При подсчете количества значений столбца эта форма функции `COUNT` не принимает во внимание значение `NULL`.
SELECT * FROM Persons WHERE name IN ('Ivan','Petr','Pavel');
```
`BETWEEN` определяет диапазон значений. В отличие от `IN`, `BETWEEN` чувствителен к порядку, и первое значение в предложении должно быть первым по алфавитному или числовому порядку.
```sql
SELECT * FROM Persons WHERE age BETWEEN 20 AND 25;
```
`LIKE` применим только к полям типа `CHAR` или `VARCHAR`, с которыми он используется чтобы находить подстроки. В качестве условия используются _символы шаблонизации (wildkards_) - специальные символы, которые могут соответствовать чему-нибудь:
+ `_` замещает любой одиночный символ. Например, `'b_t'` будет соответствовать словам `'bat'` или `'bit'`, но не будет соответствовать `'brat'`.
+ `%` замещает последовательность любого числа символов. Например `'%p%t'` будет соответствовать словам `'put'`, `'posit'`, или `'opt'`, но не `'spite'`.
В языке SQL ключевое слово `UNION` применяется для объединения результатов двух SQL-запросов в единую таблицу, состоящую из схожих записей. Оба запроса должны возвращать одинаковое число столбцов и совместимые типы данных в соответствующих столбцах. Необходимо отметить, что `UNION` сам по себе не гарантирует порядок записей. Записи из второго запроса могут оказаться в начале, в конце или вообще перемешаться с записями из первого запроса. В случаях, когда требуется определенный порядок, необходимо использовать `ORDER BY`.
`PRIMARY KEY` - набор полей (1 или более), значения которых образуют уникальную комбинацию и используются для однозначной идентификации записи в таблице. Для таблицы может быть создано только одно такое ограничение. Данное ограничение используется для обеспечения целостности сущности, которая описана таблицей.
`CHECK` используется для ограничения множества значений, которые могут быть помещены в данный столбец. Это ограничение используется для обеспечения целостности предметной области, которую описывают таблицы в базе.
`UNIQUE` обеспечивает отсутствие дубликатов в столбце или наборе столбцов.
`FOREIGN KEY` защищает от действий, которые могут нарушить связи между таблицами. `FOREIGN KEY` в одной таблице указывает на `PRIMARY KEY` в другой. Поэтому данное ограничение нацелено на то, чтобы не было записей `FOREIGN KEY`, которым не отвечают записи `PRIMARY KEY`.
По умолчанию ограничение `PRIMARY` создает кластерный индекс на столбце, а`UNIQUE` - некластерный. Другим отличием является то, что `PRIMARY` не разрешает `NULL` записей, в то время как `UNIQUE` разрешает одну (а в некоторых СУБД несколько) `NULL` запись.
`MERGE` позволяет осуществить слияние данных одной таблицы с данными другой таблицы. При слиянии таблиц проверяется условие, и если оно истинно, то выполняется `UPDATE`, а если нет - `INSERT`. При этом изменять поля таблицы в секции `UPDATE`, по которым идет связывание двух таблиц, нельзя.
`DELETE` - оператор DML, удаляет записи из таблицы, которые удовлетворяют критерию `WHERE` при этом задействуются триггеры, ограничения и т.д.
`TRUNCATE` - DDL оператор (удаляет таблицу и создает ее заново. Причем если на эту таблицу есть ссылки `FOREGIN KEY` или таблица используется в репликации, то пересоздать такую таблицу не получится).
__Хранимая процедура__ — объект базы данных, представляющий собой набор SQL-инструкций, который хранится на сервере. Хранимые процедуры очень похожи на обыкновенные процедуры языков высокого уровня, у них могут быть входные и выходные параметры и локальные переменные, в них могут производиться числовые вычисления и операции над символьными данными, результаты которых могут присваиваться переменным и параметрам. В хранимых процедурах могут выполняться стандартные операции с базами данных (как DDL, так и DML). Кроме того, в хранимых процедурах возможны циклы и ветвления, то есть в них могут использоваться инструкции управления процессом исполнения.
Хранимые процедуры позволяют повысить производительность, расширяют возможности программирования и поддерживают функции безопасности данных. В большинстве СУБД при первом запуске хранимой процедуры она компилируется (выполняется синтаксический анализ и генерируется план доступа к данным) и в дальнейшем её обработка осуществляется быстрее.
__Триггер (trigger)__ — это хранимая процедура особого типа, которую пользователь не вызывает непосредственно, а исполнение которой обусловлено действием по модификации данных: добавлением, удалением или изменением данных в заданной таблице реляционной базы данных. Триггеры применяются для обеспечения целостности данных и реализации сложной бизнес-логики. Триггер запускается сервером автоматически и все производимые им модификации данных рассматриваются как выполняемые в транзакции, в которой выполнено действие, вызвавшее срабатывание триггера. Соответственно, в случае обнаружения ошибки или нарушения целостности данных может произойти откат этой транзакции.
Момент запуска триггера определяется с помощью ключевых слов `BEFORE` (триггер запускается до выполнения связанного с ним события) или `AFTER` (после события). В случае, если триггер вызывается до события, он может внести изменения в модифицируемую событием запись. Кроме того, триггеры могут быть привязаны не к таблице, а к представлению (VIEW). В этом случае с их помощью реализуется механизм «обновляемого представления». В этом случае ключевые слова `BEFORE` и `AFTER` влияют лишь на последовательность вызова триггеров, так как собственно событие (удаление, вставка или обновление) не происходит.
__Курсор__ — это объект базы данных, который позволяет приложениям работать с записями «по-одной», а не сразу с множеством, как это делается в обычных SQL командах.
Порядок работы с курсором такой:
+ Определить курсор (`DECLARE`)
+ Открыть курсор (`OPEN`)
+ Получить запись из курсора (`FETCH`)
+ Обработать запись...
+ Закрыть курсор (`CLOSE`)
+ Удалить ссылку курсора (`DEALLOCATE`). Когда удаляется последняя ссылка курсора, SQL освобождает структуры данных, составляющие курсор.
`TIMESTAMP` хранит значение равное количеству секунд, прошедших с полуночи 1 января 1970 года по усреднённому времени Гринвича. При получении из базы отображается с учётом часового пояса. Размер: 4 байта
`PIVOT` и `UNPIVOT` являются нестандартными реляционными операторами, которые поддерживаются Transact-SQL.
Оператор `PIVOT` разворачивает возвращающее табличное значение выражение, преобразуя уникальные значения одного столбца выражения в несколько выходных столбцов, а также, в случае необходимости, объединяет оставшиеся повторяющиеся значения столбца и отображает их в выходных данных. Оператор `UNPIVOT` производит действия, обратные `PIVOT`, преобразуя столбцы возвращающего табличное значение выражения в значения столбца.
Ранжирующие функции - это функции, которые возвращают значение для каждой записи группы в результирующем наборе данных. На практике они могут быть использованы, например, для простой нумерации списка, составления рейтинга или постраничной навигации.
`ROW_NUMBER`– функция нумерации в Transact-SQL, которая возвращает просто номер записи.
`RANK` возвращает ранг каждой записи. В данном случае, в отличие от `ROW_NUMBER`, идет уже анализ значений и в случае нахождения одинаковых возвращает одинаковый ранг с пропуском следующего.
`DENSE_RANK` так же возвращает ранг каждой записи, но в отличие от `RANK` в случае нахождения одинаковых значений возвращает ранг без пропуска следующего.
`NTILE`– функция Transact-SQL, которая делит результирующий набор на группы по определенному столбцу.
SELECT id, created FROM table where id = (SELECT MAX(id) FROM table);
```
---
```sql
CREATE TABLE track_downloads (
download_id BIGINT(20) NOT NULL AUTO_INCREMENT,
track_id INT NOT NULL,
user_id BIGINT(20) NOT NULL,
download_time TIMESTAMP NOT NULL DEFAULT 0,
PRIMARY KEY (download_id)
);
```
Напишите SQL-запрос, возвращающий все пары `(download_count, user_count)`, удовлетворяющие следующему условию: `user_count` — общее ненулевое число пользователей, сделавших ровно `download_count` скачиваний `19 ноября 2010 года`:
```sql
SELECT DISTINCT download_count, COUNT(*) AS user_count
FROM (
SELECT COUNT(*) AS download_count
FROM track_downloads WHERE download_time="2010-11-19"