This media is not supported in your browser
VIEW IN TELEGRAM
Провели бенчмарк 96 комбинаций PostgreSQL 17 и 18 — и результаты местами неожиданны. 😕
В целом Postgres 18 показал себя лучше: заметные улучшения в производительности и несколько действительно интересных оптимизаций.
Подробности, результаты тестов и анализ: смотреть
👉 @SQLPortal
В целом Postgres 18 показал себя лучше: заметные улучшения в производительности и несколько действительно интересных оптимизаций.
Подробности, результаты тестов и анализ: смотреть
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤3
Не нужен весь набор данных — хватит и выборки? Тогда попробуй Postgres TABLESAMPLE.
В PostgreSQL есть встроенная функция для выборки случайных строк из таблицы. Например, чтобы взять примерно 10% строк, можно просто написать:
Удобно, когда нужно быстро глянуть структуру или прикинуть распределение данных, не прогоняя весь объём.
👉 @SQLPortal
В PostgreSQL есть встроенная функция для выборки случайных строк из таблицы. Например, чтобы взять примерно 10% строк, можно просто написать:
SELECT * FROM your_table TABLESAMPLE BERNOULLI (10);
Удобно, когда нужно быстро глянуть структуру или прикинуть распределение данных, не прогоняя весь объём.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤2
Определи, какие предыдущие строки включать в оконную функцию, с помощью
Frame задаёт, какие ключи сортировки попадут в окно (UNBOUNDED — значит все).
ROWS — строгий счётчик строк
RANGE — логический сдвиг по значению (работает только с числами и датами)
GROUPS — считает количество уникальных значений
👉 @SQLPortal
ORDER BY ... [ frame ] ... PRECEDING
Frame задаёт, какие ключи сортировки попадут в окно (UNBOUNDED — значит все).
ROWS — строгий счётчик строк
RANGE — логический сдвиг по значению (работает только с числами и датами)
GROUPS — считает количество уникальных значений
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Главный совет для разработчиков, которые только начинают работать с Postgres: всегда задавай statement timeout.
👉 @SQLPortal
ALTER DATABASE mydatabase
SET statement_timeout = '60s';
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12
Есть неагрегированные колонки, которые ты хочешь добавить в SELECT, но не в GROUP BY?
Можно использовать ANY_VALUE, например:
Функция вернёт значение из одной случайной строки (оптимизировано так, что обычно берётся первая). То есть результат — недетерминированный.
👉 @SQLPortal
Можно использовать ANY_VALUE, например:
SELECT c1, ANY_VALUE(c2), COUNT(...)
FROM ...
GROUP BY c1
Функция вернёт значение из одной случайной строки (оптимизировано так, что обычно берётся первая). То есть результат — недетерминированный.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11
Вместо удаления строк через DELETE многие приложения помечают их как удалённые, ставя флаг.
В Oracle SQL можно партиционировать по этому флагу, разделяя активные и неактивные данные.
Но есть тонкости: читать
👉 @SQLPortal
В Oracle SQL можно партиционировать по этому флагу, разделяя активные и неактивные данные.
Но есть тонкости: читать
Please open Telegram to view this post
VIEW IN TELEGRAM
Learning is not a spectator sport
Soft Deletes via Partitioning
Community friend Gwen Shapira tweeted this the other day This is a common design pattern in Oracle databases (and many others) use a DELETED_FLAG style column to handle “soft deletes.” …
👍4
Удобный приём в psql, чтобы выгрузить данные из SQL в CSV:
Команда
Это работает не только с CSV, но и с другими форматами, например:
А для любителей математики — даже в LaTeX:
👉 @SQLPortal
SELECT * FROM customers \g (format=csv) ~/Downloads/clients.csv
Команда
\g format отправляет результат запроса в указанный формат — в данном случае CSV.Это работает не только с CSV, но и с другими форматами, например:
SELECT * FROM customers \g (format=html) ~/Downloads/clients.html
А для любителей математики — даже в LaTeX:
SELECT * FROM customers \g (format=latex) ~/Downloads/clients.tex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
20 SQL-вопросов среднего уровня (с подробными ответами)
1. Напиши SQL-запрос, чтобы найти вторую по величине зарплату.
2. Как оптимизировать медленный SQL-запрос?
Используй подходящие индексы.
Избегай SELECT *, выбирай только нужные колонки.
Перепиши коррелированные подзапросы через JOIN.
Прогоняй EXPLAIN, чтобы понять план выполнения.
Разбей сложные запросы на CTE (WITH).
3. В чем разница между INNER JOIN и OUTER JOIN?
INNER JOIN: возвращает только совпадающие строки между таблицами.
OUTER JOIN: возвращает совпадающие строки и те, где нет совпадений (с NULL), бывает LEFT, RIGHT, FULL.
4. Напиши SQL-запрос, чтобы найти топ-3 отдела с самой высокой средней зарплатой.
5. Как убрать дубликаты строк в SQL-запросе?
Можно использовать DISTINCT, либо ROW_NUMBER() внутри CTE и отфильтровать лишнее:
6. Напиши SQL-запрос, чтобы найти сотрудников с одинаковыми именами в одном отделе.
7. В чем разница между UNION и UNION ALL?
UNION: убирает дубликаты.
UNION ALL: оставляет все строки, включая дубликаты.
8. Напиши SQL-запрос, чтобы найти отделы без сотрудников.
9. Как индексирование помогает ускорить запросы?
Индексы уменьшают объем данных, которые сканируются при фильтрации или джойнах.
Создавай индексы на колонках, часто используемых в WHERE, JOIN и ORDER BY.
10. Напиши SQL-запрос, чтобы найти сотрудников, работающих больше 5 лет.
11. В чем разница между SUBQUERY и JOIN?
Subquery: подзапрос внутри другого запроса, может быть вложенным.
JOIN: объединяет строки из нескольких таблиц по связанным колонкам.
12. Напиши SQL-запрос, чтобы найти топ-2 продукта с наибольшими продажами.
13. Как использование хранимых процедур может улучшить производительность запросов?
Они заранее компилируются и кешируются.
Снижают сетевой трафик, объединяя несколько операций в один вызов.
Повышают модульность и переиспользуемость.
14. Напиши SQL-запрос, чтобы найти клиентов, оформивших заказ, но не сделавших оплату.
15. В чем разница между GROUP BY и HAVING?
GROUP BY: группирует строки по одной или нескольким колонкам.
HAVING: фильтрует группы, как WHERE, но для агрегированных данных.
16. Напиши SQL-запрос, чтобы найти сотрудников, работающих в одном отделе со своим менеджером.
17. Как использовать оконные функции для решения сложных запросов?
Применяй ROW_NUMBER(), RANK(), SUM() OVER(), LAG() и т. д.
Они позволяют выполнять вычисления по нескольким строкам без группировки.
18. Напиши SQL-запрос, чтобы найти топ-3 продукта с самой высокой средней ценой.
19. В чем разница между TRUNCATE и DELETE?
TRUNCATE: удаляет все строки, быстрее, и чаще всего нельзя откатить.
DELETE: удаляет выбранные строки, поддерживает WHERE и откаты через транзакции.
👉 @SQLPortal
1. Напиши SQL-запрос, чтобы найти вторую по величине зарплату.
SELECT MAX(salary) AS SecondHighestSalary
FROM employees
WHERE salary < (SELECT MAX(salary) FROM employees);
2. Как оптимизировать медленный SQL-запрос?
Используй подходящие индексы.
Избегай SELECT *, выбирай только нужные колонки.
Перепиши коррелированные подзапросы через JOIN.
Прогоняй EXPLAIN, чтобы понять план выполнения.
Разбей сложные запросы на CTE (WITH).
3. В чем разница между INNER JOIN и OUTER JOIN?
INNER JOIN: возвращает только совпадающие строки между таблицами.
OUTER JOIN: возвращает совпадающие строки и те, где нет совпадений (с NULL), бывает LEFT, RIGHT, FULL.
4. Напиши SQL-запрос, чтобы найти топ-3 отдела с самой высокой средней зарплатой.
SELECT department_id, AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id
ORDER BY avg_salary DESC
LIMIT 3;
5. Как убрать дубликаты строк в SQL-запросе?
Можно использовать DISTINCT, либо ROW_NUMBER() внутри CTE и отфильтровать лишнее:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY name, department_id ORDER BY id) AS rn
FROM employees
)
DELETE FROM cte WHERE rn > 1;
6. Напиши SQL-запрос, чтобы найти сотрудников с одинаковыми именами в одном отделе.
SELECT name, department_id
FROM employees
GROUP BY name, department_id
HAVING COUNT(*) > 1;
7. В чем разница между UNION и UNION ALL?
UNION: убирает дубликаты.
UNION ALL: оставляет все строки, включая дубликаты.
8. Напиши SQL-запрос, чтобы найти отделы без сотрудников.
SELECT d.department_id, d.department_name
FROM departments d
LEFT JOIN employees e ON d.department_id = e.department_id
WHERE e.employee_id IS NULL;
9. Как индексирование помогает ускорить запросы?
Индексы уменьшают объем данных, которые сканируются при фильтрации или джойнах.
Создавай индексы на колонках, часто используемых в WHERE, JOIN и ORDER BY.
10. Напиши SQL-запрос, чтобы найти сотрудников, работающих больше 5 лет.
SELECT *
FROM employees
WHERE DATEDIFF(CURDATE(), hire_date) > 5 * 365;
11. В чем разница между SUBQUERY и JOIN?
Subquery: подзапрос внутри другого запроса, может быть вложенным.
JOIN: объединяет строки из нескольких таблиц по связанным колонкам.
12. Напиши SQL-запрос, чтобы найти топ-2 продукта с наибольшими продажами.
SELECT product_id, SUM(sales) AS total_sales
FROM sales_table
GROUP BY product_id
ORDER BY total_sales DESC
LIMIT 2;
13. Как использование хранимых процедур может улучшить производительность запросов?
Они заранее компилируются и кешируются.
Снижают сетевой трафик, объединяя несколько операций в один вызов.
Повышают модульность и переиспользуемость.
14. Напиши SQL-запрос, чтобы найти клиентов, оформивших заказ, но не сделавших оплату.
SELECT o.customer_id
FROM orders o
LEFT JOIN payments p ON o.order_id = p.order_id
WHERE p.payment_id IS NULL;
15. В чем разница между GROUP BY и HAVING?
GROUP BY: группирует строки по одной или нескольким колонкам.
HAVING: фильтрует группы, как WHERE, но для агрегированных данных.
16. Напиши SQL-запрос, чтобы найти сотрудников, работающих в одном отделе со своим менеджером.
SELECT e.employee_id, e.name
FROM employees e
JOIN employees m ON e.department_id = m.department_id AND e.manager_id = m.employee_id;
17. Как использовать оконные функции для решения сложных запросов?
Применяй ROW_NUMBER(), RANK(), SUM() OVER(), LAG() и т. д.
Они позволяют выполнять вычисления по нескольким строкам без группировки.
18. Напиши SQL-запрос, чтобы найти топ-3 продукта с самой высокой средней ценой.
SELECT product_id, AVG(price) AS avg_price
FROM products
GROUP BY product_id
ORDER BY avg_price DESC
LIMIT 3;
19. В чем разница между TRUNCATE и DELETE?
TRUNCATE: удаляет все строки, быстрее, и чаще всего нельзя откатить.
DELETE: удаляет выбранные строки, поддерживает WHERE и откаты через транзакции.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12
При создании индексов или частичных индексов важно понимать, какие значения встречаются чаще всего и как распределены данные по процентилям.
В PostgreSQL это можно проверить с помощью запроса к таблице pg_statistic.
👉 @SQLPortal
В PostgreSQL это можно проверить с помощью запроса к таблице pg_statistic.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Нашёл мёд для тех, кто хочет освоить Git без нудных лекций.
Есть десктопное приложение под Mac, Windows и Linux, которое обучает работе с Git через практику.
Задания выполняются прямо в реальном Git и GitHub, репозитории создаются у вас в аккаунте и остаются навсегда.
Поддержка разных языков тоже в комплекте.
Ссылка: https://github.com/jlord/git-it-electron
👉 @SQLPortal
Есть десктопное приложение под Mac, Windows и Linux, которое обучает работе с Git через практику.
Задания выполняются прямо в реальном Git и GitHub, репозитории создаются у вас в аккаунте и остаются навсегда.
Поддержка разных языков тоже в комплекте.
Ссылка: https://github.com/jlord/git-it-electron
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥3❤1
Функция generate_series в Postgres принимает три аргумента:
- стартовое значение
- конечное значение
- шаг (инкремент)
Пример:
Результат:
👉 @SQLPortal
- стартовое значение
- конечное значение
- шаг (инкремент)
Пример:
SELECT * FROM generate_series(1, 10, 2);
Результат:
1
3
5
7
9
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12
После установки октябрьского обновления 2025 года Oracle Database 23ai становится Oracle AI Database 26ai.
Теперь добавлена поддержка QUALIFY.
QUALIFY фильтрует результаты оконных функций после группировки —
так же, как HAVING фильтрует результаты агрегатных функций.
👉 @SQLPortal
Теперь добавлена поддержка QUALIFY.
QUALIFY фильтрует результаты оконных функций после группировки —
так же, как HAVING фильтрует результаты агрегатных функций.
SELECT ... FROM ...
QUALIFY fn OVER ( ... ) > ...
Please open Telegram to view this post
VIEW IN TELEGRAM
👀9
Сокращение в Postgres:
👉 @SQLPortal
USING можно использовать вместо JOIN ... ON a.id = b.idSELECT DISTINCT
t.amount AS transaction_amount
FROM
accounts a
JOIN
transactions t USING (account_id)
WHERE
a.account_id = 1;
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
Создавайте новые разделы списка при вставке новых значений ключа раздела в Oracle SQL, указав таблицу как
или преобразуйте уже существующие таблицы с помощью
Майк Смитерс показывает, как это работает.
👉 @SQLPortal
PARTITION BY LIST ( ... ) AUTOMATIC
или преобразуйте уже существующие таблицы с помощью
ALTER TABLE ... SET PARTITIONING AUTOMATICМайк Смитерс показывает, как это работает.
Please open Telegram to view this post
VIEW IN TELEGRAM
The Anti-Kyte
Getting Oracle to Create List Partitions automatically
I recently inherited the support of an application that had been written on Oracle 11g. One of the maintenance tasks was to create a new set of partitions every so often so that records with a new …
Оператор CASE в Postgres
Преобразует данные в зависимости от условия.
Оператор CASE используется для изменения (трансформации) данных в зависимости от заданного условия.
Пример выше выбирает цену из таблицы products и добавляет вычисляемое поле price_tier.
Если price больше или равна 500, в это поле записывается 'Luxury'.
Результат сортируется по цене в порядке убывания.
👉 @SQLPortal
Преобразует данные в зависимости от условия.
SELECT
price,
CASE
WHEN price >= 500.00 THEN 'Luxury'
END AS price_tier
FROM
products
ORDER BY
price DESC;
Оператор CASE используется для изменения (трансформации) данных в зависимости от заданного условия.
Пример выше выбирает цену из таблицы products и добавляет вычисляемое поле price_tier.
Если price больше или равна 500, в это поле записывается 'Luxury'.
Результат сортируется по цене в порядке убывания.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
pg_flo — библиотека для потоковой обработки в PostgreSQL
Упрощает создание и выполнение потоковых операций прямо в PostgreSQL. Она предоставляет удобный интерфейс для работы с данными и отлично подходит для задач, где нужна последовательная обработка или сложные data pipeline-ы.
GitHub: github.com/pgflo/pg_flo
👉 @SQLPortal
Упрощает создание и выполнение потоковых операций прямо в PostgreSQL. Она предоставляет удобный интерфейс для работы с данными и отлично подходит для задач, где нужна последовательная обработка или сложные data pipeline-ы.
GitHub: github.com/pgflo/pg_flo
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - pgflo/pg_flo: Stream, transform, and route PostgreSQL data in real-time.
Stream, transform, and route PostgreSQL data in real-time. - pgflo/pg_flo
👍2
dx теперь показывает «версию по умолчанию» расширений рядом с установленной версией.
Можно сравнить версии, установленные бинарно, с записями в каталоге.
Быстрая команда
исправит это.
Postgres COALESCE() и NULLIF():
Преобразовать NULL в другое значение можно с помощью COALESCE():
Сделать наоборот — превратить не-NULL значение в NULL:
👉 @SQLPortal
Можно сравнить версии, установленные бинарно, с записями в каталоге.
Быстрая команда
ALTER EXTENSION postgis UPDATE
исправит это.
Postgres COALESCE() и NULLIF():
Преобразовать NULL в другое значение можно с помощью COALESCE():
select name, coalesce(favorite_food, 'not provided') from users;
Сделать наоборот — превратить не-NULL значение в NULL:
select name, nullif(favorite_food, 'pizza') from users;
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5
Остерегайся фантомных чтений.
И в Postgres, и в MySQL возможно, что два одинаковых SELECT-запроса внутри одной и той же транзакции вернут разные результаты.
Представь, что у нас есть база и два клиента. Клиент A начинает транзакцию и делает SELECT всех заказов с суммой больше $100. Пока он выполняет другие запросы, клиент B вставляет новый заказ в таблицу и делает COMMIT. Потом клиент A снова выполняет тот же SELECT — и теперь видит новую строку, добавленную клиентом B!
Разрешено это или нет — зависит от уровня изоляции, который настроен.
В Postgres по умолчанию используется уровень READ COMMITTED, который допускает фантомные чтения. Каждый отдельный запрос видит консистентное состояние базы, но между запросами внутри одной транзакции могут появляться изменения, зафиксированные другими транзакциями.
Как и Postgres, MySQL поддерживает четыре уровня изоляции, которые можно настраивать. Более строгие уровни, вроде SERIALIZABLE, предотвращают фантомные чтения. Более «слабые», например READ COMMITTED, допускают их (по умолчанию в MySQL используется REPEATABLE READ).
Почему бы не использовать всегда SERIALIZABLE? Из-за производительности. Чем строже уровень изоляции, тем больше блокировок, и тем сильнее проседает перфоманс. Более «мягкие» уровни дают лучшую производительность, но ценой возможных неконсистентных данных.
👉 @SQLPortal
И в Postgres, и в MySQL возможно, что два одинаковых SELECT-запроса внутри одной и той же транзакции вернут разные результаты.
Представь, что у нас есть база и два клиента. Клиент A начинает транзакцию и делает SELECT всех заказов с суммой больше $100. Пока он выполняет другие запросы, клиент B вставляет новый заказ в таблицу и делает COMMIT. Потом клиент A снова выполняет тот же SELECT — и теперь видит новую строку, добавленную клиентом B!
Разрешено это или нет — зависит от уровня изоляции, который настроен.
В Postgres по умолчанию используется уровень READ COMMITTED, который допускает фантомные чтения. Каждый отдельный запрос видит консистентное состояние базы, но между запросами внутри одной транзакции могут появляться изменения, зафиксированные другими транзакциями.
Как и Postgres, MySQL поддерживает четыре уровня изоляции, которые можно настраивать. Более строгие уровни, вроде SERIALIZABLE, предотвращают фантомные чтения. Более «слабые», например READ COMMITTED, допускают их (по умолчанию в MySQL используется REPEATABLE READ).
Почему бы не использовать всегда SERIALIZABLE? Из-за производительности. Чем строже уровень изоляции, тем больше блокировок, и тем сильнее проседает перфоманс. Более «мягкие» уровни дают лучшую производительность, но ценой возможных неконсистентных данных.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥2
Совет по Postgres: если в запросах ты используешь NULLS FIRST или NULLS LAST, не забудь указать то же самое и при создании индекса.
👉 @SQLPortal
CREATE INDEX ... ON table_name (column_name DESC NULLS LAST);
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥1