This media is not supported in your browser
VIEW IN TELEGRAM
Универсальная шпаргалка по SQL, где собраны все основные конструкции языка. Всё структурировано по разделам, поэтому можно быстро найти нужный синтаксис. Формат максимально практичный: команда, пример, объяснение, что позволяет не просто смотреть, а сразу понимать, как что применяется в запросах.
Оставляю ссылочку: GitHub📱
Please open Telegram to view this post
VIEW IN TELEGRAM
🤝11👍8🔥8❤2
Как вернуть строки в том же порядке, в котором пришли id?
Когда из приложения прилетает список id, обычный
Такой запрос вернёт правильный набор строк, но порядок будет таким, как решит планировщик, а не таким, как пришёл список.
Дальше это уже обычная таблица, которую можно джойнить, фильтровать и сортировать:
В итоге база сама возвращает строки в нужном порядке, без
🔥
➡️ SQL Ready | #совет
Когда из приложения прилетает список id, обычный
WHERE id = ANY(...) находит нужные строки, но порядок входного массива не сохраняет:SELECT *
FROM users
WHERE id = ANY(ARRAY[42, 7, 99]);
Такой запрос вернёт правильный набор строк, но порядок будет таким, как решит планировщик, а не таким, как пришёл список.
WITH ORDINALITY добавляет каждой строке её позицию во входном наборе:unnest(ARRAY[42, 7, 99]) WITH ORDINALITY
Дальше это уже обычная таблица, которую можно джойнить, фильтровать и сортировать:
ORDER BY x.ord
В итоге база сама возвращает строки в нужном порядке, без
CASE, без ручной сортировки в коде и без лишнего постобработчика.WITH ORDINALITY — это простой способ сохранить порядок входных данных в SQL, он хорошо заходит в API и массовые выборки.Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🔥9🤝6❤2
Optimistic locking позволяет работать без блокировок — конфликт проверяется при записи (например, через
version или updated_at). Pessimistic locking наоборот сразу ставит блокировку (SELECT ... FOR UPDATE) и заставляет другие транзакции ждать.На картинке — как два подхода ведут себя при одновременном обновлении одной строки: в одном случае получаем conflict, в другом — очередь.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤11🔥9👍8🤝3
Почему после JOIN внезапно растут агрегаты!
Одна из самых неприятных ошибок в аналитическом SQL — когда запрос выглядит нормально, всё отрабатывает без ошибок, а цифры в итоге получаются больше, чем должны быть.
Классическая ситуация. Есть таблицы:
Допустим, хотим посчитать сумму заказов. На первый взгляд кажется, что такой запрос окей:
Но тут и начинается подвох.
Если у одного заказа 3 позиции в
Быстрая проверка, есть ли проблема:
Если строк после
Если вам нужна просто сумма по заказам, то
Если
Почему это хорошо: гранулярность
Ещё нормальный вариант — сначала убрать дубли на стороне
Тут мы заранее приводим данные к уровню одна строка = один заказ, и только потом джойним.
А если задача вообще на уровне позиций, например нужно посчитать общее количество товаров, тогда считать надо уже по
То есть важный момент очень простой: агрегировать нужно на том уровне, где реально живёт ваша метрика.
Отдельно про популярный костыль:
С виду кажется, что
Ещё неприятнее, когда
Практический способ быстро это поймать — смотреть количество строк после каждого шага:
Так обычно сразу видно, на каком
🔥 Итог простой: перед тем как писать
➡️ SQL Ready | #практика
Одна из самых неприятных ошибок в аналитическом SQL — когда запрос выглядит нормально, всё отрабатывает без ошибок, а цифры в итоге получаются больше, чем должны быть.
Классическая ситуация. Есть таблицы:
orders(id, customer_id, amount)
order_items(id, order_id, product_id, quantity)
Допустим, хотим посчитать сумму заказов. На первый взгляд кажется, что такой запрос окей:
SELECT SUM(o.amount) AS total_revenue
FROM orders o
JOIN order_items i
ON i.order_id = o.id;
Но тут и начинается подвох.
Если у одного заказа 3 позиции в
order_items, то строка из orders после JOIN повторится 3 раза. И o.amount тоже попадёт в расчёт 3 раза. В итоге сумма завышается. Это как раз тот самый fan-out: одна строка размножается после JOIN.Быстрая проверка, есть ли проблема:
SELECT
COUNT(*) AS rows_after_join,
COUNT(DISTINCT o.id) AS unique_orders
FROM orders o
JOIN order_items i
ON i.order_id = o.id;
Если строк после
JOIN стало больше, чем уникальных заказов, значит у вас fan-out по уровню orders. Что делать правильно — зависит от задачи.Если вам нужна просто сумма по заказам, то
JOIN вообще не нужен:SELECT SUM(amount)
FROM orders;
Если
JOIN нужен только для фильтрации, например по конкретному товару, безопаснее использовать EXISTS:SELECT SUM(o.amount)
FROM orders o
WHERE EXISTS (
SELECT 1
FROM order_items i
WHERE i.order_id = o.id
AND i.product_id = 10
);
Почему это хорошо: гранулярность
orders не ломается. Один заказ остаётся одной строкой.Ещё нормальный вариант — сначала убрать дубли на стороне
order_items:SELECT SUM(o.amount)
FROM orders o
JOIN (
SELECT DISTINCT order_id
FROM order_items
WHERE product_id = 10
) i ON i.order_id = o.id;
Тут мы заранее приводим данные к уровню одна строка = один заказ, и только потом джойним.
А если задача вообще на уровне позиций, например нужно посчитать общее количество товаров, тогда считать надо уже по
order_items:SELECT SUM(i.quantity)
FROM order_items i;
То есть важный момент очень простой: агрегировать нужно на том уровне, где реально живёт ваша метрика.
Отдельно про популярный костыль:
SELECT SUM(DISTINCT o.amount)
FROM orders o
JOIN order_items i
ON i.order_id = o.id;
С виду кажется, что
DISTINCT сейчас всё починит, на деле — нет. Почему это плохая идея: если у двух разных заказов одинаковый amount, один из них просто схлопнется; запрос начинает давать вроде бы правдоподобный, но неверный результат.Ещё неприятнее, когда
JOIN не один, а цепочка: orders — order_items — products — categoriesПрактический способ быстро это поймать — смотреть количество строк после каждого шага:
SELECT COUNT(*) FROM orders;
SELECT COUNT(*)
FROM orders
JOIN order_items ON order_items.order_id = orders.id;
SELECT COUNT(*)
FROM orders
JOIN order_items ON order_items.order_id = orders.id
JOIN products ON products.id = order_items.product_id;
Так обычно сразу видно, на каком
JOIN начинаются лишние строки.JOIN, всегда держите в голове гранулярность данных. Что у вас является одной строкой: заказ, позиция заказа, клиент? Сначала определяете уровень данных — потом джойните и агрегируете.Please open Telegram to view this post
VIEW IN TELEGRAM
❤13🔥10👍8🤝2
В этой статье:
• Показано, как в YDB обрабатывается SQL-запрос — от парсинга до распределённого исполнения по узлам;
• Разбирается, как устроены планировщик, оптимизатор и механизмы шардинга при работе с большими данными;
• Объясняется, как достигаются консистентность, отказоустойчивость и масштабируемость в распределённой базе.🔊 Продолжайте читать на Habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤11🔥7👍6🤝3
В системах с временными интервалами важно понимать не просто отдельные события, а их наложение — именно оно определяет реальную нагрузку.
Сегодня в задаче:
• Преобразуем интервалы в точки начала и конца, чтобы работать с ними как с потоком событий;
• Посчитаем текущую нагрузку через накопительную сумму по времени;
• Найдём момент максимального количества одновременных событий — пик нагрузки системы.
Этот приём используется в мониторинге, аналитике, планировщиках и системах, где важно контролировать параллельную активность.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤13👍8🔥7🤝4
This media is not supported in your browser
VIEW IN TELEGRAM
Здесь публикуются ежедневные статьи, обучающие серии Stairway, подборки скриптов, обзоры книг, а также активные форумы и блоги для администраторов БД и разработчиков.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9👍9🔥8🤝2
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17🤝9❤7🔥2
This media is not supported in your browser
VIEW IN TELEGRAM
Если хочется быстро разобраться в командах — этот сайт отлично подойдёт. Конструкции объяснены на примерах, с чётким и кратким синтаксисом. Удобно использовать как справочник или экспресс‑повторение.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤15🔥8👍7🤝3
Например, Primary Key гарантирует уникальность записей, Foreign Key — обеспечивает ссылочную целостность, а JOIN’ы позволяют собирать распределённые данные в единую выборку.
На картинке — основные концепции, которые используются при проектировании и работе с БД.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17❤8🤝8
Проверяем дубликаты и считаем уникальные значения!
В больших таблицах важно быстро находить повторяющиеся записи и понимать, сколько уникальных элементов. Это полезно для контроля качества данных и аналитики.
Создадим таблицу пользователей:
Запрос для выявления дубликатов и подсчёта уникальных email:
Функция
Результат:
🔥 Это простой способ контролировать качество данных, выявлять ошибки и готовить отчёты для команды.
➡️ SQL Ready | #практика
В больших таблицах важно быстро находить повторяющиеся записи и понимать, сколько уникальных элементов. Это полезно для контроля качества данных и аналитики.
Создадим таблицу пользователей:
CREATE TABLE users (
user_id INT,
email VARCHAR(100)
);
INSERT INTO users VALUES
(1, 'alice@mail.com'),
(2, 'bob@mail.com'),
(3, 'alice@mail.com'),
(4, 'carol@mail.com'),
(5, 'bob@mail.com');
Запрос для выявления дубликатов и подсчёта уникальных email:
SELECT email, COUNT(*) AS cnt,
CASE WHEN COUNT(*)>1 THEN 'Duplicate' ELSE 'Unique' END AS status
FROM users
GROUP BY email;
Функция
COUNT() + GROUP BY группирует одинаковые значения, а CASE сразу классифицирует их как дубликаты или уникальные.Результат:
email | cnt | status
-----------------------------
alice@mail.com | 2 | Duplicate
bob@mail.com | 2 | Duplicate
carol@mail.com | 1 | Unique
🔥 Это простой способ контролировать качество данных, выявлять ошибки и готовить отчёты для команды.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18🔥7🤝6❤4
Использование data-modifying CTE для цепочек операций в одном запросе!
Обычно изменения и чтение делают разными запросами, что создаёт лишние
Теперь можно атомарно обновить данные и сразу записать аудит, отправить в очередь или выполнить дополнительную логику без повторных
🔥
➡️ SQL Ready | #совет
Обычно изменения и чтение делают разными запросами, что создаёт лишние
round-trip и риск рассинхронизации данных между операциями:UPDATE orders
SET status = 'processing'
WHERE id = 123
RETURNING *;
RETURNING уже даёт доступ к изменённым строкам, но data-modifying CTE позволяет пойти дальше и использовать их в следующих шагах:WITH updated AS (...)
CTE фиксирует результат изменения и гарантирует, что последующие операции работают с тем же набором строк в рамках одного statement:INSERT INTO audit_log (order_id, new_status)
SELECT id, status
FROM updated;
Теперь можно атомарно обновить данные и сразу записать аудит, отправить в очередь или выполнить дополнительную логику без повторных
SELECT.data-modifying CTE — это способ строить сложные, но безопасные цепочки операций внутри одного SQL-запроса.Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🔥10🤝8