🔍 BETWEEN в SQL: удобный инструмент фильтрации, но есть нюансы
В SQL оператор BETWEEN используется для фильтрации значений в заданном диапазоне, включая границы этого диапазона. Синтаксис прост, но за ним скрываются важные детали, особенно при работе с датами и временем.
Общий синтаксис:
Это полностью эквивалентно:
Границы включаются! Это главный момент, который необходимо помнить.
Пример с числами:
Этот запрос вернёт все товары, цена которых от 100 до 500 включительно.
То же самое, что:
Обратите внимание: порядок имеет значение!
Если перепутать границы — результат будет пустым:
Пример с датами:
На первый взгляд запрос безопасен, но всё зависит от типа данных order_date
— Если это DATE, то всё хорошо: вернутся все заказы от 1 января до 31 декабря 2024 года включительно.
— Если это DATETIME или TIMESTAMP, то 31 декабря попадут только записи с временем 00:00:00. То есть, большая часть заказов за 31 декабря может быть пропущена!
Как правильно писать условия для DATETIME.
Используйте открытый верхний предел:
Такой стиль абсолютно безопасен и широко применяется в профессиональной практике, особенно в BI и аналитике.
Что ещё важно?
1. Типы данных должны быть совместимы
BETWEEN работает и с текстами (сравнение лексикографическое), и с датами, и с числами.
2. NOT BETWEEN тоже существует!
Возвращает все строки, где значение меньше 18 или больше 60.
BETWEEN и NULL:
Если значение в проверяемом столбце — NULL, то условие BETWEEN вернёт не TRUE, а UNKNOWN, что эквивалентно тому, что строка не попадёт в результат.
Чтобы явно включить такие строки, добавьте отдельное условие:
Итого:
1. BETWEEN включает границы, то есть условие BETWEEN 10 AND 20 вернёт и 10, и 20.
2. При работе с типами DATETIME следует быть особенно осторожным: BETWEEN '2024-01-01' AND '2024-12-31' не захватит все записи за 31 декабря, если в них указано время.
3. BETWEEN чувствителен к порядку значений: если нижняя граница больше верхней — результат будет пустой.
4. Не забывайте про NULL: записи с NULL в проверяемом столбце не попадут в выборку.
5. Альтернативный и более безопасный способ — использовать условия вида >= ... AND < ..., особенно при работе с временными диапазонами.
В целом, BETWEEN — удобный инструмент, если применять его правильно с учётом особенностей данных, с которыми вы работаете.
#BETWEEN #SQL
📱 Подписаться на канал | Курс автора по SQL DDL
В SQL оператор BETWEEN используется для фильтрации значений в заданном диапазоне, включая границы этого диапазона. Синтаксис прост, но за ним скрываются важные детали, особенно при работе с датами и временем.
Общий синтаксис:
SELECT ...
FROM ...
WHERE столбец BETWEEN значение_1 AND значение_2;
Это полностью эквивалентно:
WHERE столбец >= значение_1 AND столбец <= значение_2
Границы включаются! Это главный момент, который необходимо помнить.
Пример с числами:
SELECT * FROM products
WHERE price BETWEEN 100 AND 500;
Этот запрос вернёт все товары, цена которых от 100 до 500 включительно.
То же самое, что:
WHERE price >= 100 AND price <= 500
Обратите внимание: порядок имеет значение!
Если перепутать границы — результат будет пустым:
WHERE price BETWEEN 500 AND 100
-- Вернёт 0 строк
Пример с датами:
SELECT * FROM orders
WHERE order_date BETWEEN '2024-01-01' AND '2024-12-31';
На первый взгляд запрос безопасен, но всё зависит от типа данных order_date
— Если это DATE, то всё хорошо: вернутся все заказы от 1 января до 31 декабря 2024 года включительно.
— Если это DATETIME или TIMESTAMP, то 31 декабря попадут только записи с временем 00:00:00. То есть, большая часть заказов за 31 декабря может быть пропущена!
Как правильно писать условия для DATETIME.
Используйте открытый верхний предел:
WHERE order_date >= '2024-01-01'
AND order_date < '2025-01-01'
Такой стиль абсолютно безопасен и широко применяется в профессиональной практике, особенно в BI и аналитике.
Что ещё важно?
1. Типы данных должны быть совместимы
WHERE product_id BETWEEN 'a' AND 'z' -- OK для строк
BETWEEN работает и с текстами (сравнение лексикографическое), и с датами, и с числами.
2. NOT BETWEEN тоже существует!
WHERE age NOT BETWEEN 18 AND 60;
Возвращает все строки, где значение меньше 18 или больше 60.
BETWEEN и NULL:
Если значение в проверяемом столбце — NULL, то условие BETWEEN вернёт не TRUE, а UNKNOWN, что эквивалентно тому, что строка не попадёт в результат.
SELECT * FROM employees
WHERE commission_pct BETWEEN 0.1 AND 0.3; -- NULL значения исключаются
Чтобы явно включить такие строки, добавьте отдельное условие:
WHERE (commission_pct BETWEEN 0.1 AND 0.3 OR commission_pct IS NULL)
Итого:
1. BETWEEN включает границы, то есть условие BETWEEN 10 AND 20 вернёт и 10, и 20.
2. При работе с типами DATETIME следует быть особенно осторожным: BETWEEN '2024-01-01' AND '2024-12-31' не захватит все записи за 31 декабря, если в них указано время.
3. BETWEEN чувствителен к порядку значений: если нижняя граница больше верхней — результат будет пустой.
4. Не забывайте про NULL: записи с NULL в проверяемом столбце не попадут в выборку.
5. Альтернативный и более безопасный способ — использовать условия вида >= ... AND < ..., особенно при работе с временными диапазонами.
В целом, BETWEEN — удобный инструмент, если применять его правильно с учётом особенностей данных, с которыми вы работаете.
#BETWEEN #SQL
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥19👾4🤯2💯1
🔗 Типы связей в реляционных БД: что, зачем и как?
Связи между таблицами — основа реляционных баз данных. Именно они позволяют создавать сложные модели данных. В теории баз данных тип связи (relationship type) — это формализованное описание ассоциации между двумя или более сущностями, указывающее, сколько экземпляров одной сущности может быть связано с экземплярами другой.
Я часто встречал базовые задания на изменение типа связи к оптимальному на собеседованиях для системных аналитиков. Разберёмся, какие бывают типы связей и как они реализуются.
1. Один к одному (1:1)
Каждая запись в таблице A соответствует ровно одной записи в таблице B и наоборот.
Пример:
Таблица users — содержит пользователей
Таблица passports — содержит паспортные данные
Каждому пользователю соответствует один паспорт, и каждый паспорт — одному пользователю.
Как реализуется:
Вторичная таблица (passports) содержит внешний ключ на users. id
Иногда связи 1:1 выделяются в отдельную таблицу для повышения безопасности или для разделения редко используемых данных
Связь: users. id (PK) — 1:1 — passports.user_id (PK, FK)
2. Один ко многим (1:N)
Каждая запись в таблице A может соответствовать нескольким записям в таблице B, но каждая запись в таблице B соответствует только одной записи в A.
Пример:
Таблица departments — отделы
Таблица employees — сотрудники
Один отдел включает многих сотрудников, но каждый сотрудник относится к одному отделу.
Как реализуется:
Во второй таблице (employees) создаётся внешний ключ department_id, указывающий на departments. id первой таблицы. Это — самый распространённый тип связи.
Связь: departments. id (PK) — 1:N — employees.department_id (FK)
3. Многие ко многим (N:M)
Каждая запись в таблице A может соответствовать нескольким записям в таблице B, и наоборот.
Пример:
Таблица students — студенты
Таблица courses — курсы
Один студент записан на много курсов, и каждый курс включает много студентов.
Как реализуется:
1. Создаётся связующая таблица (например, student_course)
2. Она содержит два внешних ключа: student_id и course_id
3. Иногда добавляют дополнительные атрибуты
Связи:
1. students. id — 1:N — student_courses.student_id
2. courses. id — 1:N — student_courses.course_id
Коротко о реализации типов связей:
1. Один к одному — внешний ключ + уникальность
2. Один ко многим — внешний ключ в "многой" таблице
3. Многие ко многим — связующая таблица с 2 FK
Почему это важно?
Правильное определение и реализация связей:
1. Обеспечивает целостность данных
2. Обязательно для нормализации данных и устранения дублирования
4. Необходимо для поддержки бизнес-логики и целевого использования данных БД
5. Улучшает производительность (меньше дублирования, легче кэшировать);
6. Делает базу пригодной к росту (easy to scale).
Таким образом, связи в реляционной БД — это основа структурированной, надёжной и масштабируемой системы хранения данных.
#Ключи_и_связи_между_таблицами #SQL
📱 Подписаться на канал | Курс автора по SQL DDL
Связи между таблицами — основа реляционных баз данных. Именно они позволяют создавать сложные модели данных. В теории баз данных тип связи (relationship type) — это формализованное описание ассоциации между двумя или более сущностями, указывающее, сколько экземпляров одной сущности может быть связано с экземплярами другой.
Я часто встречал базовые задания на изменение типа связи к оптимальному на собеседованиях для системных аналитиков. Разберёмся, какие бывают типы связей и как они реализуются.
1. Один к одному (1:1)
Каждая запись в таблице A соответствует ровно одной записи в таблице B и наоборот.
Пример:
Таблица users — содержит пользователей
Таблица passports — содержит паспортные данные
Каждому пользователю соответствует один паспорт, и каждый паспорт — одному пользователю.
Как реализуется:
Вторичная таблица (passports) содержит внешний ключ на users. id
Иногда связи 1:1 выделяются в отдельную таблицу для повышения безопасности или для разделения редко используемых данных
users passports
+---------+ +------------+
| id (PK) <--- |user_id (PK,FK)
| name |passport_number
+---------+ +------------+
Связь: users. id (PK) — 1:1 — passports.user_id (PK, FK)
2. Один ко многим (1:N)
Каждая запись в таблице A может соответствовать нескольким записям в таблице B, но каждая запись в таблице B соответствует только одной записи в A.
Пример:
Таблица departments — отделы
Таблица employees — сотрудники
Один отдел включает многих сотрудников, но каждый сотрудник относится к одному отделу.
Как реализуется:
Во второй таблице (employees) создаётся внешний ключ department_id, указывающий на departments. id первой таблицы. Это — самый распространённый тип связи.
departments employees
+----------+ +-----------------+
| id (PK) <----- | id (PK)
| name | name
+----------+ | department_id(FK)
+-----------------+
Связь: departments. id (PK) — 1:N — employees.department_id (FK)
3. Многие ко многим (N:M)
Каждая запись в таблице A может соответствовать нескольким записям в таблице B, и наоборот.
Пример:
Таблица students — студенты
Таблица courses — курсы
Один студент записан на много курсов, и каждый курс включает много студентов.
Как реализуется:
1. Создаётся связующая таблица (например, student_course)
2. Она содержит два внешних ключа: student_id и course_id
3. Иногда добавляют дополнительные атрибуты
students student_courses
+---------+ +--------------+
| id (PK) | student_id(FK)
| name | course_id(FK)
+---------+ +--------------+
courses
+----------+
| id (PK)
| noscript
+----------+
Связи:
1. students. id — 1:N — student_courses.student_id
2. courses. id — 1:N — student_courses.course_id
Коротко о реализации типов связей:
1. Один к одному — внешний ключ + уникальность
2. Один ко многим — внешний ключ в "многой" таблице
3. Многие ко многим — связующая таблица с 2 FK
Почему это важно?
Правильное определение и реализация связей:
1. Обеспечивает целостность данных
2. Обязательно для нормализации данных и устранения дублирования
4. Необходимо для поддержки бизнес-логики и целевого использования данных БД
5. Улучшает производительность (меньше дублирования, легче кэшировать);
6. Делает базу пригодной к росту (easy to scale).
Таким образом, связи в реляционной БД — это основа структурированной, надёжной и масштабируемой системы хранения данных.
#Ключи_и_связи_между_таблицами #SQL
Please open Telegram to view this post
VIEW IN TELEGRAM
👾9🔥5🌚1
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7👾5🤯1
Рассказываю, как создать локальную тестовую БД для практики буквально за пару минут.
Для начала качаем DBeaver, это бесплатное программное обеспечение с открытым исходным кодом, распространяемое по лицензии Apache, по сути клиент для SQL и инструмент для администрирования баз данных.
После установки запускаем приложение и в меню кликаем: Справка → Создать тестовую базу данных (всё показал на скринах последовательно). В результате получаем полноценную базу данных на SQLite.
Но есть нюанс, у SQLite несколько ограниченный функционал по сравнению с обычными СУБД (например, нет поддержи RIGHT JOIN, FULL OUTER JOIN), однако, для практики, я думаю, это не помеха.
P.S. на последнем скрине для проверки создал в новой БД таблицу, все ок
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👾5💯2
Подготовили пост про хард скиллс в SQL совместно с @bashnya_education 👾
🔥4👾1
Forwarded from БАШНЯ
HARD SKILLS❗️
Продолжаем разбирать hard skills🔥
Сегодня поговорим про SQL - что это такое и что спрашивают по нему на собеседованиях👨💻
Делитесь этим постом с друзьями и пишите свои вопросы в комментарии ✍️
Автор поста:
Владимир Лунев, ментор в Башне
#hardskills
Продолжаем разбирать hard skills
Сегодня поговорим про SQL - что это такое и что спрашивают по нему на собеседованиях
Делитесь этим постом с друзьями и пишите свои вопросы в комментарии ✍️
Автор поста:
Владимир Лунев, ментор в Башне
#hardskills
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15👾6💯4
Please open Telegram to view this post
VIEW IN TELEGRAM
🤣25🗿11🌚3
Привет, ранее уже базово затрагивал темы обычных представлений и материализованных, однако, сегодня словил желание остановится на MView по подробнее.
🧊 Что такое материализованное представление?
Материализованное представление (Materialized View) — это реальный объект базы данных, содержащий предрасчитанные данные.
В отличие от обычного VIEW, здесь:
🧊 Архитектурно материализованное представление — это:
🧊 Ключевые особенности
🧊 Общий синтаксис для создания материализованного представления:
CREATE MATERIALIZED VIEW имя_представления AS
SELECT ...
FROM ...
[WHERE ...]
[GROUP BY ...]
[ORDER BY ...];
Дополнительно можно указать:
WITH NO DATA — представление создаётся, но не заполняется (нужно REFRESH).
WITH DATA (по умолчанию) — данные вычисляются сразу при создании.
🧊 Допустим, у нас есть таблица orders, в которой хранятся заказы клиентов. Она может содержать такие поля:
-----------------------------
id SERIAL
order_date TIMESTAMP
customer_id INT
amount NUMERIC
Таблица обновляется постоянно: пользователи делают заказы, и каждая строка — это один заказ.
Часто требуется строить отчёты:
Запрос к такой таблице может быть тяжёлым, особенно если в orders миллионы строк. Поэтому создаём материализованное представление — заранее рассчитанный агрегат, чтобы анализировать среднюю сумму заказов по дням:
CREATE MATERIALIZED VIEW daily_avg_orders AS
SELECT
order_date::date AS day,
COUNT(*) AS total_orders,
AVG(amount) AS avg_order_value
FROM orders
GROUP BY day
ORDER BY day;
Что делает это материализованное представление:
После выполнения CREATE MATERIALIZED VIEW — СУБД физически сохраняет результат запроса. Теперь мы можем быстро выполнять:
SELECT * FROM daily_avg_orders;
И получать результат без перерасчёта данных каждый раз.
🛠 Обновление (refresh)
Чтобы MView оставалось актуальным, его нужно обновлять вручную или автоматически.
При ручном обновлении, чтобы обновить данные в представлении после изменений в таблице orders, выполняем:
REFRESH MATERIALIZED VIEW daily_avg_orders;
Если при создании добавили WITH NO DATA — первый REFRESH обязателен.
Можно настроить автообновление через:
⚙️ Индексы и уникальность
Во многих СУБД материализованные представления поддерживают индексы, особенно если нужно обеспечить уникальность:
CREATE UNIQUE INDEX ON имя_представления(ключ);
Для того чтобы представление можно было обновлять инкрементально (а не полностью), часто требуется уникальный ключ.
👾 Где это особенно нужно?
Так что, материализуемся
#Views #Materialized_views #SQL
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👾3💯2 2
Привет, нашел прикольную шпаргалку по основным джоинам от ByteByteGo.
Для инфо, JOIN в SQL — это операция, которая позволяет объединять данные из двух или более таблиц по связанному столбцу (обычно по ключу: первичному и внешнему).
Ранее писал посты про базовые джоины, однако, есть еще куча необычных join-операторов, конечно, в обиходе не все они используются часто, но кто знает, куда неофитов могут завести скитания по базе данных 😂
Скоро напишу пост про специфические джоины.
Лайк если надо👩💻
Для инфо, JOIN в SQL — это операция, которая позволяет объединять данные из двух или более таблиц по связанному столбцу (обычно по ключу: первичному и внешнему).
Ранее писал посты про базовые джоины, однако, есть еще куча необычных join-операторов, конечно, в обиходе не все они используются часто, но кто знает, куда неофитов могут завести скитания по базе данных 😂
Скоро напишу пост про специфические джоины.
Лайк если надо
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥28👾4😱2
Итак, давайте разберем необычные виды join, про которые не так часто вспоминают, но они по своему прекрасны. Погнали.
SELF JOIN используется, когда нам нужно сравнить строки внутри одной и той же таблицы.
SELECT e1.name AS employee, e2.name AS manager
FROM employees e1
JOIN employees e2 ON e1.manager_id = e2.id;
Где полезен:
Обратить внимание:
Каждая строка из первой таблицы соединяется со всеми строками второй.
SELECT c.color, s.size
FROM colors c
CROSS JOIN sizes s;
Где полезен:
Пример:
Таблица colors:
red
blue
Таблица sizes:
S
M
L
Результат:
color size
red S
red M
red L
blue S
blue M
blue L
Обратить внимание:
Автоматически соединяет таблицы по колонкам с одинаковыми именами и типами.
SELECT *
FROM orders
NATURAL JOIN customers;
Где полезен:
Обратить внимание:
Ищем строки в первой таблице, у которых нет пары во второй.
На SQL делается через:
SELECT c.id
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id
WHERE o.id IS NULL;
ИЛИ:
SELECT c.id
FROM customers c
WHERE NOT EXISTS (
SELECT 1 FROM orders o WHERE o.customer_id = c.id
);
Где полезен:
Обратить внимание:
Найти строки из одной таблицы, у которых есть хотя бы одна пара в другой таблице, но не вытаскивать её. Забавно, но его синтаксис это JOIN без JOIN:
SELECT c.id
FROM customers c
WHERE EXISTS (
SELECT 1 FROM orders o WHERE o.customer_id = c.id
);
В отличие от INNER JOIN, мы не получаем orders.* — только customers.
Где полезен:
Обратить внимание:
Поддержка:
#Join #SQL
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14 6💯4
Пишу пост про SQLi*, до конца недели опубликую. В июле, скорее всего буду много говорить о безопасности БД, методах их защиты, плюс затронем выдачу и управление правами пользователей в СУБД и бэкапы.
*⚠️ SQL-инъекция (SQL injection)— это атака, при которой злоумышленник внедряет вредоносный SQL-код через поля ввода, например, на сайте (логин, пароль, поисковая строка), чтобы получить несанкционированный доступ к базе данных.
*
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9🌚7 5
This media is not supported in your browser
VIEW IN TELEGRAM
Когда удалил не ту таблицу. Ну, главное, чтобы не на проде 😂
🤣16🔥5😱3🌚2
Привет, вписался в конкурс каналов с качественным авторским контентом. Потом будут голосования за лучшие посты по номинациям среди каналов и все такое — здесь @tg_contest_main. Так что, не удивляйтесь, иногда буду просить вас голосовать))
Ну а вобще, я считаю, круто, что мой канал начинает участвовать в таких штуках, для меня это своеобразный признак оценки моих стараний (как и ваши реакции)😁
Ну а вобще, я считаю, круто, что мой канал начинает участвовать в таких штуках, для меня это своеобразный признак оценки моих стараний (как и ваши реакции)
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15🌚3💯3