SQL Ready | Базы Данных
Авторский канал про Базы Данных и SQL Ресурсы, гайды, задачи, шпаргалки. Информация ежедневно пополняется! Автор: @energy_it РКН: https://clck.ru/3QREBc Реклама на бирже: https://telega.in/c/sql_ready
Mostrar más📈 Análisis del canal de Telegram SQL Ready | Базы Данных
El canal SQL Ready | Базы Данных (@sql_ready) en el segmento lingüístico de Ruso es un actor destacado. Actualmente la comunidad reúne a 15 559 suscriptores, ocupando la posición 8 396 en la categoría Tecnologías y Aplicaciones y el puesto 43 154 en la región Rusia.
📊 Métricas de audiencia y dinámica
Desde su creación el невідомо, el proyecto ha mostrado un crecimiento acelerado, reuniendo a 15 559 suscriptores.
Según los últimos datos del 11 junio, 2026, el canal mantiene una actividad estable. En los últimos 30 días la variación de miembros fue de 56, y en las últimas 24 horas de -9, conservando un alto alcance.
- Estado de verificación: No verificado
- Tasa de interacción (ER): El promedio de interacción de la audiencia es 12.41%. Durante las primeras 24 horas tras publicar, el contenido suele obtener 6.30% de reacciones respecto al total de suscriptores.
- Alcance de las publicaciones: Cada publicación recibe en promedio 1 931 visualizaciones. En el primer día suele acumular 980 visualizaciones.
- Reacciones e interacción: La audiencia responde de forma activa: el promedio de reacciones por publicación es 24.
- Intereses temáticos: El contenido se centra en temas clave como sql, строка, user_id, created_at, desc.
📝 Descripción y política de contenido
El autor describe el recurso como un espacio para expresar opiniones subjetivas:
“Авторский канал про Базы Данных и SQL
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!
Автор: @energy_it
РКН: https://clck.ru/3QREBc
Реклама на бирже: https://telega.in/c/sql_ready”
Gracias a la alta frecuencia de actualizaciones (últimos datos recibidos el 12 junio, 2026), el canal mantiene la vigencia y un amplio alcance. La analítica demuestra que la audiencia interactúa activamente con el contenido, lo que lo convierte en un punto de referencia dentro de la categoría Tecnologías y Aplicaciones.
now() - created_at
Если нужно получить возраст записи в читаемом виде (годы-месяцы-дни), есть функция age(), которая учитывает календарь, а не просто секунды:
SELECT age(now(), created_at)
FROM orders;
А когда требуется число дней или часов для аналитики, интервал можно сразу привести к нужной единице:
EXTRACT(EPOCH FROM now() - created_at) / 3600
🔥 Полезно для TTL-логики, SLA-метрик, мониторинга задержек и любых задач, где время жизни записи, является ключевым параметром.
➡️ SQL Ready | #советDATE хранит дату и время одновременно. Частая задача — сравнить только по дате, игнорируя время. Многие используют TRUNC(date), но это может сильно ухудшить производительность.
Представим таблицу:
orders(id, created_at DATE)
Нужно выбрать заказы за 18 февраля 2026.
Интуитивный вариант:
SELECT *
FROM orders
WHERE TRUNC(created_at) = DATE '2026-02-18';
Логически верно, но есть проблема.
Функция применяется к колонке — поэтому обычный индекс по created_at в основном не используется, и Oracle вынужден вычислять TRUNC для множества строк, что часто приводит к полному сканированию.
Правильный способ — диапазон по дате:
SELECT *
FROM orders
WHERE created_at >= DATE '2026-02-18'
AND created_at < DATE '2026-02-19';
Теперь условие индекс-дружелюбное (sargable) — оптимизатор может использовать обычный индекс по created_at.
Этот подход корректно работает независимо от времени в поле.
TRUNC(date) полезен в SELECT или GROUP BY, когда фильтрация по индексу не критична:
SELECT
TRUNC(created_at) AS day,
COUNT(*) AS orders_count
FROM orders
GROUP BY TRUNC(created_at)
ORDER BY day;
Если всё же нужно часто фильтровать по TRUNC(created_at), можно создать функциональный индекс:
CREATE INDEX idx_orders_created_day
ON orders (TRUNC(created_at));
После этого запрос с TRUNC сможет использовать индекс.
Функция TRUNC умеет обрезать дату до разных уровней:
SELECT
TRUNC(SYSDATE) AS day,
TRUNC(SYSDATE, 'MM') AS month_start,
TRUNC(SYSDATE, 'YYYY') AS year_start
FROM dual;
Поддерживаются форматы: DD (день), MM (месяц), YYYY (год), IW (ISO-неделя) и др.
DATE хранит дату со временем, поэтому = DATE '2026-02-18' не находит все записи за день; функции над колонками мешают индексам.
🔥 Для фильтрации по дате используйте диапазоны, а TRUNC — для отображения, агрегации или вместе с функциональным индексом.
➡️ SQL Ready | #практика• Показано, как устроена учебная база, приближенная к реальным продакшен-сценариям с миллионами записей;
• Разобрано, как генерируются правдоподобные данные через имитацию работы системы, включая бронирования и жизненный цикл событий;
• Объясняется, какие задачи по SQL, аналитике и производительности можно отрабатывать на такой базе.
🔊 Продолжайте читать на Habr!➡️ SQL Ready | #статья
JOIN часто увеличивает результат или заставляет делать DISTINCT, что бьёт по производительности:
SELECT *
FROM orders o
WHERE EXISTS (
SELECT 1 FROM payments p
WHERE p.order_id = o.id
);
EXISTS останавливается на первой найденной строке и не создаёт дубликатов, поэтому обычно работает быстрее и предсказуемее:
SELECT *
FROM orders o
WHERE NOT EXISTS (
SELECT 1 FROM payments p
WHERE p.order_id = o.id
);
NOT EXISTS - наиболее корректный способ найти записи без соответствующих связанных данных.
В отличие от NOT IN он корректнее работает при наличии NULL:
SELECT *
FROM orders o
LEFT JOIN payments p ON p.order_id = o.id
WHERE p.order_id IS NULL;
🔥 LEFT JOIN + IS NULL делает то же самое логически, но чаще требует больше работы оптимизатора и может уступать по производительности на больших объёмах.
➡️ SQL Ready | #советorders(id, customer_id, amount, created_at)
Хотим увидеть все заказы и одновременно понимать, сколько денег каждый клиент потратил в сумме.
Первая мысль — посчитать через GROUP BY:
SELECT
customer_id,
SUM(amount) AS total_amount
FROM orders
GROUP BY customer_id;
Да, сумму он посчитает. Но список заказов пропадёт — останется по одной строке на клиента.
Если коротко: GROUP BY считает по группе, но детали внутри группы выбрасывает.
Решение через оконную функцию:
SELECT
id,
customer_id,
amount,
SUM(amount) OVER (PARTITION BY customer_id) AS total_amount
FROM orders;
PARTITION BY customer_id разбивает строки на независимые окна по клиентам.
SUM(...) OVER (...) считает сумму внутри каждого окна, но строки не схлопывает — каждая остаётся на месте.
В результате каждая строка — отдельный заказ и total_amount — сумма всех заказов этого клиента.
Фильтрация по агрегату без GROUP BY — например, нужно выбрать только заказы тех клиентов, у которых суммарный оборот больше 1000:
SELECT *
FROM (
SELECT
*,
SUM(amount) OVER (PARTITION BY customer_id) AS total_amount
FROM orders
) t
WHERE total_amount > 1000;
Обратите внимание: фильтрация происходит уже после вычисления оконной функции. Никаких GROUP BY, никаких дополнительных JOIN.
Та же логика через JOIN (для сравнения):
SELECT o.*
FROM orders o
JOIN (
SELECT customer_id, SUM(amount) AS total_amount
FROM orders
GROUP BY customer_id
) s ON s.customer_id = o.customer_id
WHERE s.total_amount > 1000;
Работает, но выглядит тяжелее: отдельный подзапрос, джойн, дублирование таблицы.
Можно посчитать сразу несколько агрегатов по тем же окнам:
SELECT
id,
customer_id,
amount,
SUM(amount) OVER (PARTITION BY customer_id) AS total_amount,
COUNT(*) OVER (PARTITION BY customer_id) AS orders_count
FROM orders;
Получаем и общую сумму, и количество заказов клиента — прямо в каждой строке.
🔥 Используйте оконные функции, когда нужно посчитать итог по группе, но не потерять сами строки. Это базовый приём аналитического SQL, который постоянно встречается в реальных задачах.
➡️ SQL Ready | #практикаTransport Subsystem — приём запроса от клиента по сетевому протоколу, установка сессии, а Query Processor — синтаксический и семантический разбор, построение дерева запроса (parse tree).
На схеме показан полный путь запроса — от клиента до хранения данных.
Сохрани, чтобы не забыть!
➡️ SQL Ready | #ресурсprefix%. Но при поиске по подстроке (%text%) или сложных шаблонах они обычно не используются, и запрос превращается в полный скан таблицы даже на миллионах строк.
CREATE EXTENSION IF NOT EXISTS pg_trgm;
Расширение pg_trgm добавляет триграммные индексы, которые эффективно ищут подстроки, частичные совпадения и нечёткие шаблоны:
CREATE INDEX users_email_trgm_idx
ON users USING gin (email gin_trgm_ops);
После этого запросы вроде:
SELECT *
FROM users
WHERE email ILIKE '%company%';
Начинают использовать индекс и ускоряются, особенно для поиска по почте, логинам, URL и другим текстовым идентификаторам:
EXPLAIN ANALYZE
SELECT *
FROM users
WHERE email ILIKE '%company%';
🔥 Важно: триграммный индекс занимает больше места и замедляет INSERT/UPDATE, но для больших таблиц с поиском по подстроке это почти всегда оправдано.
➡️ SQL Ready | #советОставляю ссылочку: GitHub 📱➡️ SQL Ready | #репозиторий
VIEW — сохранённый запрос, как объект схемы. Для обычных VIEW данные не дублируются: оптимизатор, как правило, раскрывает их в подзапрос и строит единый план (зависит от СУБД):
SELECT *
FROM active_users
WHERE email LIKE '%@company.com';
Логика фильтрации находится в одном месте, без копирования условий по коду.
CREATE OR REPLACE VIEW active_users AS
SELECT id, name, email
FROM users
WHERE deleted_at IS NULL
AND NOT is_blocked;
CREATE OR REPLACE позволяет централизованно менять логику (если сохраняется совместимый контракт колонок), не переписывая клиентские запросы:
GRANT SELECT ON active_users TO reporting_role;
🔥 Права можно выдавать на VIEW, а не на таблицу, скрывая лишние поля и фиксируя допустимую проекцию (механика зависит от СУБД).
➡️ SQL Ready | #совет
¡Ya disponible! Investigación de Telegram 2025 — los principales insights del año 
