Функции ранжирования и нумерации в Transact-SQL; ROW_NUMBER, RANK, DENSE_RANK, NTILE
Функции ранжирования и нумерации в Transact-SQL — ROW_NUMBER, RANK, DENSE_RANK, NTILE
Изучение Transact-SQL продолжается и на очереди у нас функции ранжирования ROW_NUMBER, RANK, DENSE_RANK и NTILE, сейчас мы узнаем, что делают эти функции и зачем вообще они нужны, все как обычно будем рассматривать на примерах.
В языке Transact-SQL очень много различных функций, конструкций, например, PIVOT или INTERSECT, которые в принципе редко используются, их мы даже в нашем мини справочнике Transact-SQL не указывали, но знать, где и как их можно использовать нужно, так же, как и функции ранжирования или их еще называют функции нумерации. Поэтому сегодня давайте поговорим именно об этих функциях, и если говорить конкретно, то это функции: ROW_NUMBER, RANK, DENSE_RANK, NTILE.
И начнем мы, конечно же, с определения, что же вообще это за ранжирующие функции.
Данные
В контексте баз данных под данными понимают набор значений, который собирается в строки и столбцы, тем самым представляя таблицу. Представим, что у нас есть каталог мебельного магазина. Нам нужно сохранить все данные из раздела «Шкафы» этого каталога в таблицу. Мы решили, что все шкафы отличаются друг от друга характеристиками:
- название производителя;
- название модели;
- высота;
- длина;
- цвет;
- количество дверей.
Составим таблицу и вобьём в неё выдуманные данные.
У нас есть таблица с данными. Столбцами мы показываем, как они будут храниться. В примере я указал, что мы будем хранить информацию в структуре: производитель, модель, высота, длина, цвет, количество дверей. Иными словами, я создал структуру таблицы.
Добавляя в таблицу строки, я вводил в неё данные, ориентируясь на структуру, заданную в столбцах. Чем больше строк, тем больше данных. Чем больше столбцов, тем подробнее будут эти данные.
Ещё есть такое понятие, как «значение» — это пересечение столбца и строки. Например, у последней строки в столбце «Цвет» написано «хаки». Здесь «хаки» — значение. Если мы начнём группировать таблицы и добавим возможность манипулирования ими, то получим базу данных.
SQL-операторы: руководство с примерами запросов. Часть 2
Перевод второй части статьи «SQL Operators Tutorial – Bitwise, Comparison, Arithmetic, and Logical Operator Query Examples».
В первой части статьи мы рассмотрели такие темы:
В этой части мы рассмотрим:
Операторы для проверки существования (IN / NOT IN)
Если мы хотим проверить, есть ли определенное значение в списке значений, мы можем воспользоваться операторами IN или NOT IN :
Аналогично, для отрицания используется NOT IN :
Частичное совпадение — использование LIKE
Иногда нам нужно найти строки, основываясь на частичном совпадении.
Допустим, мы хотим найти всех пользователей, которые зарегистрировались в нашем приложении при помощи адреса Gmail. Мы можем поискать частичное совпадение в столбце, используя ключевое слово LIKE . Также при этом можно использовать групповой символ — % .
Поиск пользователей, чей email оканчивается на gmail.com :
Строка %gmail.com означает «совпадение со всем, что кончается на gmail.com».
Если мы посмотрим на данные наших пользователей, мы заметим, что среди них только у двоих адрес электронной почты кончается на gmail.com :
Но в email Джейн указана заглавная «G». Предыдущий запрос не выберет эту запись, потому что мы ищем точное совпадение с gmail.com, а там «g» в нижнем регистре.
Чтобы поиск не зависел от регистра, нужно заменить LIKE на ILIKE :
Групповой символ % в начале строки означает, что вернуть нужно все, что заканчивается на «gmail.com». Это может быть и ob.jones+12345@gmail.com, и asdflkasdflkj@gmail.com — главное, чтобы в конце стояло «gmail.com».
Мы также можем использовать столько групповых символов, сколько нам нужно.
Например, поиск %j%o% вернет любой email-адрес, соответствующий шаблону «<все-что-угодно>, за чем следует j, за чем следует <все-что-угодно>, за чем следует o, за чем следует <все-что-угодно>»:
Работа с отсутствующими данными (NULL)
Давайте посмотрим, как быть со столбцами и строками, где нет данных.
Для этого давайте добавим в нашу таблицу users еще один столбец: first_paid_at .
Этот новый столбец будет TIMESTAMP (подобно datetime в других языках) и будет представлять дату и время, когда пользователь впервые заплатил нам за наше приложение. Может, мы хотим послать ему открытку и цветы в честь годовщины.
Мы могли бы стереть нашу таблицу users , введя DROP TABLE users , и пересоздать ее заново, но таким образом мы удалили бы все данные в таблице.
Чтобы изменить таблицу, не стирая ее и не лишаясь данных, можно использовать ALTER TABLE :
Эта команда возвращает результат ALTER TABLE , так что наш запрос ALTER сработал успешно.
Если мы теперь запросим нашу таблицу users , мы заметим, что теперь в ней появился новый столбец без данных:
Наш столбец first_paid_at пуст, и результат нашего psql-запроса показывает, что это пустой столбец. Технически он не пустой: в нем содержится специальное значение, которое psql просто не показывает в выводе — NULL .
NULL это специальное значение в базах данных. Это отсутствие значения, и оно ведет себя не так, как можно было бы ожидать.
Чтобы это продемонстрировать, давайте посмотрим на простой SELECT :
Здесь мы просто выбрали 1 = 1 и 1 = 2 . Как мы и ожидали, результат этих двух предложений — t и f (или TRUE и FALSE ). 1 равен 1, но 1 не равен 2.
Теперь давайте попробуем проделать то же самое с NULL :
Мы могли ожидать, что значением будет FALSE , но на деле возвращается значение NULL .
Чтобы еще лучше визуализировать NULL , давайте при помощи опции pset посмотрим, как psql отображает NULL-значения:
Если мы запустим этот запрос еще раз, мы увидим в выводе ожидаемый нами NULL :
Итак, 1 не равен NULL , а как насчет NULL = NULL ?
Довольно странно, однако NULL не равен NULL .
NULL лучше представлять себе как неизвестное значение. Равно ли неизвестное значение единице? Мы не знаем, оно же неизвестное. Равно ли неизвестное значение неизвестному значению? Опять же, мы этого не знаем. Это немного лучше поясняет, что такое NULL .
Использование IS NULL и IS NOT NULL
Мы не можем использовать с NULL оператор равенства, но мы можем пользоваться двумя специально созданными для этого операторами: IS NULL и IS NOT NULL .
Эти значения ожидаемы: NULL IS NULL — истина, NULL IS NOT NULL — ложь.
Это все прекрасно и очень интересно, но как это применять на практике?
Что ж, для начала давайте заведем какие-то данные в нашем столбце first_paid_at :
В приведенной выше инструкции UPDATE мы задали значения для столбца first_paid_at у троих разных пользователей: пользователю с ID 1 — текущее время ( NOW() ), пользователю с ID 2 — текущее время минус месяц, а пользователю с ID 3 — текущее время минус год.
Во-первых, давайте найдем пользователей, которые нам уже платили, и пользователей, которые пока этого не делали:
Операторы сравнения при работе с датами и временем
Теперь, когда у нас есть кое-какие данные, давайте используем те же операторы сравнения применительно к новому полю TIMESTAMP .
Попробуем найти пользователей, которые совершили платеж на протяжении последней недели. Для этого мы можем взять текущее время ( NOW() ) и вычесть из него одну неделю при помощи ключевого слова INTERVAL :
Мы также можем использовать другой интервал, например, последние три месяца:
Теперь давайте найдем пользователей, которые совершали платеж в промежутке от одного до шести месяцев назад.
Мы можем скомбинировать наши условия, используя AND , но вместо использования операторов < и > давайте используем ключевое слово BETWEEN :
Проверка существования с использованием EXISTS / NOT EXISTS
Другой способ проверить существование (наличие) значения — использовать EXISTS и NOT EXISTS .
Эти операторы фильтруют строки, проверяя существование или несуществование условия. Это условие обычно является запросом к другой таблице.
Чтобы это продемонстрировать, давайте создадим новую таблицу под названием posts . В этой таблице будут содержаться посты, котоыре пользователь может делать в нашей системе.
Это простая таблица. Она содержит только ID, поле для хранения текста поста ( body ) и ссылку на пользователя, который написал этот пост ( user_id ).
Давайте добавим в новую таблицу некоторые данные:
Согласно добавленным данными, у пользователя с ID 1 есть два поста, у пользователя с ID 2 — один пост, у пользователя с ID 3 — тоже один пост.
Чтобы найти пользователей, у которых есть посты, мы можем использовать ключевое слово EXISTS .
EXISTS принимает подзапрос. Если этот подзапрос возвращает что-либо (даже строку со значением NULL ), база данных включит эту строку в результат.
EXISTS проверяет лишь существование строки из подзапроса, ему не важно, что именно содержится в этой строке.
Вот пример выборки пользователей, имеющих посты:
Как и ождилалось, мы получили пользователей с ID 1, 2 и 3.
Наш подзапрос EXISTS проверяет записи в таблице posts, где user_id поста совпадает со столбцом id таблицы users. Мы вернули 1 в нашем SELECT , потому что здесь мы можем вернуть что угодно: база данных просто хочет видеть, что что-то вернулось.
Аналогично, мы можем найти пользователей, у которых нет постов. Для этого нужно заменить EXISTS на NOT EXISTS :
Наконец, мы можем переписать наш запрос и использовать IN или NOT IN вместо EXISTS или NOT EXISTS :
Технически это сработает, но вообще, если вы проверяете существование другое записи, более производительно будет использовать EXISTS . Операторы IN и NOT IN в целом лучше применять для проверки значения в статическом списке, как мы делали ранее:
Поразрядные операторы
Хотя на практике поразрядные операторы используются нечасто, для полноты картины давайте рассмотрим простой пример.
Если мы по какой-то причине хотим посмотреть возраст наших пользователей в бинарном виде и поиграться с перестановкой битов, мы можем использовать поразрядные операторы.
В качестве примера давайте рассмотрим поразрядный оператор «and»: & .
Чтобы осуществить поразрядную операцию, нам сначала нужно преобразовать значения в нашем столбце age из целых чисел в бинарный формат. В данном случае мы использовали ::bit(8) и получили восьмибитовые строки.
Далее мы можем «сложить» результат в бинарном формате с другой строкой в бинарном формате — 11111111 . Поскольку бинарный AND возвращает единицу только если оба бита это единицы, эта добавочная строка делает вывод интересным.
Практически все остальные поразрядные операторы используют тот же формат:
Поразрядный оператор «not» (
) немного отличается. Он применяется к одному термину, так же, как и обычный оператор NOT :
И, наконец, самый полезный из поразрядных операторов: конкатенация.
Этот оператор обычно используется для склейки вместе строк текста. Например, если мы хотим составить вычисленное «полное имя» для пользователей, мы можем воспользоваться конкатенацией:
Здесь мы для создания значения name сконкатенировали (скомбинировали) first_name , пробел ( ‘ ‘ ) и last_name .
Заключение
Итак, мы рассмотрели практически все операторы фильтрации, котоыре вам могут понадобиться в работе!
Есть еще несколько, о которых мы не упоминали, но они либо используются не слишком часто, либо используются точно так же, как те, что мы разобрали, так что у вас не должно возникнуть проблем с ними.
От редакции Techrocks: возможно, вам будет интересна еще одна статья того же автора: SQL JOIN: руководство по объединению таблиц.
Предложение LIMIT
Используя предложение LIMIT , мы можем получить только некоторое количество строк из больших блоков данных. Это помогает ограничить количество строк, возвращаемых в результирующем наборе. Предположим, что в таблице существуют тысячи строк, но нам требуется только 10 записей, тогда вместо извлечения тысяч записей это предложение помогает получить лишь 10 записей. Это действительно помогает настраивать производительность при поиске больших наборов данных.
С предложением LIMIT можно передавать один или два аргумента. В случае двух аргументов один из них будет смещением, которое задает сдвиг первой возвращаемой строки от начала. В то время как второй аргумент будет количеством, которое задает максимальное количество строк, которые будут возвращены. Этот аргумент должен быть нулевым или положительным. Взгляните на приведенный ниже запрос, где мы извлекли 10 записей из таблицы пользователей, начиная с 5-й строки.
Если с предложением LIMIT указать всего один аргумент, то аргумент будет считаться количеством строк. Например, следующий ниже запрос используется для извлечения 10 строк из таблицы пользователей:
На данный момент мы видели получение данных из одной таблицы; если мы хотим получить данные из нескольких таблиц, используются ключевые слова JOIN и UNION .
Шпаргалка по LINQ и SQL
Последовательность, — любая коллекция, реализующая интерфейс IEnumerable<> или IQueryable<>. Оператор запроса — метод, преобразующий последовательность. Запрос — выражение, которое преобразует последовательность с помощью операторов запроса.
Синтаксис
LINQ поддерживает два вида синтаксиса: синтаксис запросов и синтаксис методов
Синтаксис запросов:
Такой синтаксис всегда должен начинаться с from in и заканчиваться select или group. Синтаксис методов:
Все стандартные методы реализованы как расширяющие, большинство из них принимает в параметр лямбда-выражение или делегат.
Методы можно применять один за другим:
Оба вида синтаксиса можно использовать вместе.
Лямбда-выражения
Лямбда-выражения — это специальный синтаксис для сокращённого объявления анонимных методов.
Пример синтаксиса: n => n * n Это выражение принимает один параметр (n) и возвращает n * n.
Пример использования:
=> — лямбда оператор, который читается как "переходит в".
Слева от лямбда оператора стоят параметры ввода, справа — выражение
Это лямбда-выражение эквивалентно такому: n => < return n * n; >и такому delegate(int n) < return n * n; >
Стандартные операторы запроса используют обобщенные делегаты Func, например Func<int, bool> соответствует лямбда-выражению int => bool, а Func<string, string, int> — (string, string) => int
Возвращаемое значение Func всегда указывается в качестве последнего аргумента.
В лямбда-выражения можно использовать внешние переменные:
Отложенное выполнение
Большая часть операторов запроса выполняется не при конструировании, а только при переборе элементов.
Пример:
Это называется отложенным или ленивым выполнением, оно характерно для всех операторов запроса, кроме операторов, возвращающих один элемент (First) или значение (Sum), а также для операторов преобразования типа (ToArray, ToList)
Расширяющие методы
Поскольку все операторы запроса реализованы в виде расширяющих методов, можно легко добавить собственные
Несколько примеров расширяющих методов для LINQ. Метод, обратный методу Where, возвращает последовательность, элементы которой не удовлетворяют предикату
Метод, возвращающий последовательность от и до определенных индексов
Определение минимального и максимального числа в массиве
Определение суммы чисел в массиве
Изменяет порядок элементов последовательности на противоположный
Возвращает различающиеся элементы последовательности
Возвращает только те элементы последовательности first, которых нет в последовательности second
Находит пересечение множеств, представленных двумя последовательностями
Проецирует матрицу в последовательность
Находит объединение множеств, представленных двумя последовательностями
SELECT
SELECT — оператор DML языка SQL, возвращающий набор данных (выборку) из базы данных, удовлетворяющих заданному условию.
вернёт все столбцы всех строк данной таблицы. Для той же таблицы запрос
вернёт те же строки, что и первый, однако результат будет отсортирован в обратном порядке (Z-A) из-за использования ключевого слова ORDER BY с полем C1 в качестве поля сортировки
DESC – обратный порядок (последний элемент будет 1 в списке)
ASC – сортировать от первого элемента к последнему (1 элемент будет первым в списке)
Отбирает все строки где поле column_name равен одному из перечисленных значений value1,value2,…
COUNT(*) в MySQL
Метод COUNT(*) используется для подсчета количества строк, находящихся в таблице, или подсчета количества строк в соответствии с заданным условием. Чтобы проверить общее количество строк в таблице, «social» попробуйте запрос ниже.
Взгляните на метод COUNT(*) при определении некоторых условий. Нам нужно получить количество строк, в которых имя пользователя совпадает с «AndreyEx».
Чтобы получить общую сумму строк, в которых веб-сайт пользователя – «Instagram», попробуйте запрос, указанный ниже.
Чтобы получить общее количество строк, в которых «Возраст» больше 18, выполните следующие действия:
Давайте возьмем данные столбцов «User» и «Website» из таблицы, где имя пользователя начинается с буквы «M». Попробуйте приведенную ниже инструкцию по оболочке.
Доступна электронная поставка «1С:КИП»
Сейчас «1С:Корпоративный инструментальный пакет» в обязательном порядке входит в состав поставки лицензий «1С:Предприятие» уровня КОРП. При этом для таких клиентских и серверных лицензий уже достаточно давно существует вариант электронной поставки.
Очевидно, что заказ всех необходимых компонентов в рамках одного варианта поставки будет более удобным для пользователей. Как минимум, это позволит существенно сократить срок поставки до нескольких дней.
По цене и функциональным возможностям коробочный и появившийся недавно электронный вариант не отличаются.