SQL и Анализ данных
12.4K subscribers
601 photos
53 videos
3 files
630 links
Базы данных и всё, что с ними связано!

Сотрудничество: @haarrp

РКН № 6001430881
Download Telegram
🚀 УСКОРЕНИЕ ТРАНЗАКЦИЙ В SQL ЧЕРЕЗ BATCHING !

Ускоряй SQL-транзакции с помощью batched inserts/updates и минимизации количества round‑trip'ов

Одна из главных причин медленных транзакций — множество отдельных запросов. Каждый INSERT или UPDATE — это отдельная поездка в базу (round-trip), которая стоит времени и ресурсов.

Решение: объединяй операции в батчи, используй VALUES (...), (...), (...) или CASE WHEN для обновлений.

Пример:


-- Вместо этого (медленно):
INSERT INTO logs (user_id, action) VALUES (1, 'login');
INSERT INTO logs (user_id, action) VALUES (2, 'logout');
INSERT INTO logs (user_id, action) VALUES (3, 'login');

-- Делай так (быстрее):
INSERT INTO logs (user_id, action)
VALUES
(1, 'login'),
(2, 'logout'),
(3, 'login');

-- Аналогично для обновлений:
UPDATE accounts
SET balance = CASE user_id
WHEN 1 THEN 100
WHEN 2 THEN 200
WHEN 3 THEN 300
END
WHERE user_id IN (1, 2, 3);


📌 Преимущества:
– Меньше сетевых вызовов
– Лучше используется план выполнения
– Меньше блокировок и нагрузка на транзакционный лог
👍15🔥42
🖥 SQL-задача с подвохом: почему запрос работает не так, как ожидаешь?

🧠 Условие:

Есть таблица orders:

| id | customer_id | total |
|----|-------------|--------|
| 1 | A | 100.00 |
| 2 | A | 200.00 |
| 3 | B | 150.00 |
| 4 | B | 300.00 |
| 5 | C | 400.00 |


Нужно выбрать заказ с максимальной суммой (`total`) для каждого клиента.

Вы пишете:


SELECT customer_id, MAX(total)
FROM orders
GROUP BY customer_id;


Работает? Да. Но теперь вы хотите вернуть всю строку заказа с максимальной суммой — включая id.

Вы пишете:


SELECT *
FROM orders
GROUP BY customer_id
HAVING total = MAX(total);


Ошибка. Или — неожиданные результаты.

📌 Подвох: нельзя использовать HAVING total = MAX(total) без подзапроса.
MAX — агрегат, а total вне GROUP BY — это ошибка или неопределённость.

Правильное решение — с подзапросом:


SELECT o.*
FROM orders o
JOIN (
SELECT customer_id, MAX(total) AS max_total
FROM orders
GROUP BY customer_id
) t ON o.customer_id = t.customer_id AND o.total = t.max_total;


💡 Такое решение:

🟢Возвращает всю строку заказа с максимальной суммой
🟢Работает корректно даже при одинаковых суммах у нескольких заказов
🟢Избегает путаницы с агрегатами в основном SELECT

🧠 Вывод:
Нельзя просто так использовать MAX() и при этом возвращать столбцы вне GROUP BY.
Для этого всегда нужен JOIN с агрегатом или window-функции.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍91🔥1💊1
🖥 Мощный учебник по SQL — охватывает всё от базы до продвинутого уровня.

Внутри — 4 модуля, разбитые по сложности:
🟣 Основы SQL
🟣 Средний уровень
🟣 Продвинутый SQL
🟣 Аналитика на SQL

📚 Каждый модуль — это около 10 практичных уроков с возможностью сразу применять знания.

📌 Ссылка тут:
https://mode.com/sql-tutorial
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8👍2🥰1
🔐 Postgresus - self-hosted инструмент для резервного копирования и мониторинга PostgreSQL базы данных, написанный на Go

🔥 Возможности:
- создание бекапов по расписанию для PostgreSQL 13-17;
- уведомления в Telegram, Slack, Discord, если бекап сломался или база недоступна;
- хранение бекапов локально, в S3 или Google Drive;
- health check базы данных раз в минуту.

Запуск через Docker:

docker run -d \
--name postgresus \
-p 4005:4005 \
-v ./postgresus-data:/postgresus-data \
--restart unless-stopped \
rostislavdugin/postgresus:latest


📌 GitHub
🔥4👍2🥰1
📘 OpenAI выпустила GPT-5 Prompting Guide — руководство по созданию эффективных промтов

Что внутри:
- 🛠 Agentic workflows — как настраивать автономность модели и управлять глубиной размышлений (`reasoning_effort`).
- 📋 Tool preambles — структура работы с инструментами: цель, план, комментарии, итог.
- Responses API — альтернатива Chat Completions для экономии токенов и улучшения качества.
- 💻 Кодинг — советы по интеграции в Next.js, React, Tailwind и оптимизации стиля кода.
- 🎯 Steering & verbosity — контроль длины и стиля ответа, избегание конфликтующих инструкций.
- 🚀 Minimal reasoning mode — быстрые задачи с чётким планом и приоритетами.
- 🔄 Метапромтинг — использование GPT-5 для улучшения собственных промтов.

Кому полезно:
Разработчикам агентных систем, AI-ассистентов и всем, кто хочет выжать максимум из GPT-5.

🔗 Полный гайд и примеры

#GPT5 #PromptEngineering #OpenAI #AI
6🔥3👍2
This media is not supported in your browser
VIEW IN TELEGRAM
🗓️ SQL-трюк: как быстро найти "дыры" в данных по датам

В аналитике часто нужно понять, за какие дни нет записей — например, продаж или логов.
Вместо сложных процедур можно сгенерировать календарь через generate_series() (Postgres) и сделать LEFT JOIN к данным. Так вы мгновенно выявите пропуски и сможете строить непрерывные временные ряды.


-- Дни без заказов за последние 30 дней
WITH calendar AS (
SELECT generate_series(
current_date - interval '30 days',
current_date,
interval '1 day'
)::date AS day
),
orders_per_day AS (
SELECT
order_ts::date AS day,
COUNT(*) AS orders_count
FROM sales
WHERE order_ts >= current_date - interval '30 days'
GROUP BY order_ts::date
)
SELECT
c.day,
COALESCE(o.orders_count, 0) AS orders_count
FROM calendar c
LEFT JOIN orders_per_day o USING(day)
WHERE o.orders_count IS NULL
ORDER BY c.day;


https://www.youtube.com/shorts/CAkHyUx6iiU

#SQL #Postgres #DataAnalytics #generate_series
👍148🔥4
🔍 DVC — Git для данных и ML-моделей. Этот инструмент делает для данных то же, что Git для кода — позволяет отслеживать изменения, переключаться между версиями и работать в команде без хаоса.

DVC не загружает тяжелые файлы в Git-репозиторий, а хранит их в облаке или локально, записывая только метаданные. Особенно удобна интеграция с ML-пайплайнами: можно настраивать зависимости между этапами обработки данных и обучения, а он будет перезапускать только изменившиеся части. При этом инструмент отлично дополняет MLflow: первый управляет версиями данных, второй — трекит эксперименты.

🤖 GitHub
👍52🔥1
🖥 Задача (Oracle SQL, продвинутая): управление запасами с MODEL, скользящим спросом и детектом «stockout»

Таблицы:
• items(item_id NUMBER, init_qty NUMBER) — стартовый остаток по товару
• movements(item_id NUMBER, ts DATE, qty NUMBER) — движения: приход (qty>0) и расход (qty<0), событий может быть несколько в день

Нужно:
1) Построить помесячный/подневный календарь по каждому item_id между мин(ts) и max(ts).
2) Посчитать ежедневный итоговый остаток (onhand), применяя суммарные дневные движения к старту, даже если в конкретный день не было событий.
3) Найти «окна нулевого остатка» (stockout): количество, самую длинную протяжённость и дату первого пополнения после самого длинного окна.
4) Спрогнозировать риск обнуления в ближайшие 14 дней при текущем тренде: взять 7-дневное скользящее среднее спроса (по расходам), спроецировать остаток и отметить товары, которые уйдут в ноль.



-- Демоданные
WITH items AS (
SELECT 101 item_id, 50 init_qty FROM dual UNION ALL
SELECT 102, 5 FROM dual
),
movements_raw AS (
SELECT 101 item_id, DATE'2025-08-01' ts, 30 qty FROM dual UNION ALL -- приход
SELECT 101, DATE'2025-08-02', -20 FROM dual UNION ALL -- расход
SELECT 101, DATE'2025-08-04', -40 FROM dual UNION ALL -- перерасход → stockout
SELECT 101, DATE'2025-08-06', 60 FROM dual UNION ALL -- пополнение
SELECT 102, DATE'2025-08-01', - 2 FROM dual UNION ALL
SELECT 102, DATE'2025-08-03', - 3 FROM dual UNION ALL
SELECT 102, DATE'2025-08-05', 5 FROM dual
),
-- 1) Свернём движения по дням (может быть несколько событий в день)
movements AS (
SELECT item_id, ts, SUM(qty) qty_per_day
FROM movements_raw
GROUP BY item_id, ts
),



-- 1) Календарь на ежедневной сетке для каждого товара
date_bounds AS (
SELECT item_id,
LEAST(MIN(ts), TRUNC(SYSDATE)) AS dmin,
GREATEST(MAX(ts), TRUNC(SYSDATE)) AS dmax
FROM movements
GROUP BY item_id
),
calendar AS (
SELECT b.item_id, (b.dmin + LEVEL - 1) d
FROM date_bounds b
CONNECT BY LEVEL <= b.dmax - b.dmin + 1
AND PRIOR item_id = item_id
AND PRIOR SYS_GUID() IS NOT NULL
),



-- 2) Посчитаем ежедневный остаток MODEL-ом
onhand AS (
SELECT item_id, d, onhand, qty_per_day
FROM (
SELECT c.item_id,
c.d,
NVL(m.qty_per_day, 0) qty_per_day,
i.init_qty
FROM calendar c
JOIN items i USING(item_id)
LEFT JOIN movements m ON m.item_id = c.item_id AND m.ts = c.d
)
MODEL
PARTITION BY (item_id)
DIMENSION BY (d)
MEASURES (init_qty, qty_per_day, CAST(NULL AS NUMBER) AS onhand)
RULES SEQUENTIAL ORDER (
onhand[MIN(d)] = init_qty[MIN(d)] + qty_per_day[MIN(d)],
onhand[FOR d FROM MIN(d)+1 TO MAX(d)] =
onhand[CV(d)-1] + qty_per_day[CV(d)]
)
),



-- 3) Найдём окна нулевого остатка и их длины
stockout_runs AS (
SELECT *
FROM onhand
MATCH_RECOGNIZE (
PARTITION BY item_id
ORDER BY d
MEASURES
FIRST(d) AS start_d,
LAST(d) AS end_d,
COUNT(*) AS days_zero
ONE ROW PER MATCH
PATTERN (z+)
DEFINE
z AS onhand = 0
)
),



-- 3) Для самого длинного окна найдём дату первого пополнения после него
longest_zero AS (
SELECT s.item_id, s.start_d, s.end_d, s.days_zero,
LEAD(s.end_d) OVER (PARTITION BY s.item_id ORDER BY s.days_zero, s.end_d) dummy
FROM (
SELECT s.*, ROW_NUMBER() OVER (PARTITION BY item_id ORDER BY days_zero DESC, end_d) rn
FROM stock
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥32
Forwarded from Machinelearning
🚀 GLM-4.5V — новый лидер в open-source визуальном рассуждении .

Модель показывает лучшие результаты в своём классе среди открытых решений, лидируя на 41 бенчмарке.

📌 Возможности:
- Image Reasoning — понимание изображений, анализ нескольких изображений, распознавание объектов.
- Video Understanding — раскадровка длинных видео, определение событий, которые происходят на кадрах из видео.
- GUI-задачи — понимание интрефейсов, распознавание иконок, кнопок и тд, помощь в управлении рабочим столом.
- Сложный анализ графиков и документов — разбор различных отчётов, извлечение информации их них.
- Grounding — точная локализация элементов на изображениях.

📌 Особенности:
🟠 Основана на GLM-4.5-Air и использует наработки из GLM-4.1V-Thinking.

🟠 Архитектура — MoE с 106B параметров для эффективного масштабирования.

Здесь можно почитать про GLM-4.5, а здесь посмотреть техрепорт, там много интересного.

🟢 Hugging Face: https://huggingface.co/zai-org/GLM-4.5V
🟢 GitHub: https://github.com/zai-org/GLM-V
🟢 Документация API: https://docs.z.ai/guides/vlm/glm-4.5v
🟢 Попробовать: https://chat.z.ai

@ai_machinelearning_big_data

#GLM #opensource #vlm
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍1🔥1
👣 Schema — CLI-инструмент для работы с БД (SQLite, libSQL, PostgreSQL, MySQL, MariaDB)
GitHub: gigagrug/schema

Что умеет:
- schema -i — инициализация проекта (по умолчанию SQLite + `./schema/dev.db`) или подключение к выбранной БД
- schema -pull — импорт существующей структуры
- Миграции:
- создание SQL-файлов
- применение (`schema -migrate`)
- выборочное выполнение (`schema -migrate="имя"`)
- Миграции с данными для повторного использования
- Выполнение произвольных SQL прямо в консоли
- Встроенная TUI-студия для интерактивной работы с БД

📌 Почему стоит попробовать:
- Быстрые и наглядные миграции
- Поддержка нескольких СУБД
- Легкое подключение к существующей базе
- Совмещает миграции, генерацию данных и интерактивный интерфейс

📌 Apache-2.0 • 22 звезды • 8 релизов • последний — 2 августа 2025

Если нужен удобный CLI для миграций и работы с базами — Schema точно стоит внимания.

👉 Github
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍1🔥1
🐘 Tarantool — необычная платформа, сочетающая in-memory базу данных с полноценным сервером приложений на Lua. Проект имеет два движка хранения: in-memory с WAL и LSM-дерево, поддерживает ANSI SQL и асинхронную репликацию.

Инструмент имеет встроенный JIT-компилятор LuaJIT, позволяющий исполнять бизнес-логику прямо рядом с данными. При этом сохраняется совместимость с внешними СУБД вроде PostgreSQL через коннекторы. Проект полезен для высоконагруженных веб-сервисов, кэширующих слоёв и систем обработки очередей сообщений.

🤖 GitHub

@databases_tg
3👍3🔥3
💡 Полезный хинт для Oracle SQL — ускоряем поиск по последним записям с KEEP (DENSE_RANK ...)

Вместо подзапросов для поиска последнего или первого значения по группе можно использовать аналитическую агрегацию с KEEP (DENSE_RANK ...). Это делает код короче и часто быстрее.

📍 Пример: для каждой акции получить последнюю цену

select symbol,
max(price) keep (dense_rank last order by ts) as last_price,
max(ts) as last_ts
from trades
group by symbol;


📍 Первый тик за день:

select trunc(ts) as trade_day,
symbol,
min(price) keep (dense_rank first order by ts) as first_price
from trades
group by trunc(ts), symbol;


Плюсы:

- Нет лишних джоинов и подзапросов
- Работает прямо в GROUP BY
- Удобно для задач «последнее значение по группе»
👍72🥰1🤨1
⚡️ SQL на Python: безопасные IN-списки без лимитов + потоковая выборка

Используй «расширяемые» параметры IN в SQLAlchemy + потоковую выборку — это безопаснее, быстрее и не бьёт по памяти. Вместо склейки списка ID в строку передай Python-список как параметр с expanding=True: драйвер сам подставит нужное число плейсхолдеров и корректно закэширует план. Совмести это с итерацией по результатам (chunks) — и обрабатывай миллионы строк без OOM. Ставь лайк и подпишись на нас, каждый день мы публикуем полезные и не банальные советы для разработчиков.


pip install sqlalchemy pandas
from typing import Iterable, Sequence, Dict, Any
import pandas as pd
from sqlalchemy import create_engine, text, bindparam, tuple_
from sqlalchemy.engine import Engine, Result

# Пример: engine для Postgres/Oracle/MySQL и т.д.
# engine = create_engine("postgresql+psycopg://user:pass@host/db")
# engine = create_engine("oracle+oracledb://user:pass@tnsname")

def stream_query_in(engine: Engine, table: str, id_list: Sequence[int], chunk_rows: int = 50_000) -> Iterable[pd.DataFrame]:
"""
Потоково выбирает строки по большому списку ID:
- безопасно подставляет массив в IN (:ids) через expanding=True
- возвращает пачки DataFrame фиксированного размера (chunk_rows)
"""
# 1) Готовим SQL с расширяемым параметром
stm = text(f"SELECT * FROM {table} WHERE id IN :ids").bindparams(
bindparam("ids", expanding=True)
)
with engine.connect() as conn:
# 2) Выполняем запрос одним списком (драйвер сам развернёт IN)
result: Result = conn.execution_options(stream_results=True).execute(stm, {"ids": list(id_list)})

# 3) Потоково собираем фреймы по chunk_rows строк
batch = []
for row in result:
batch.append(dict(row._mapping))
if len(batch) >= chunk_rows:
yield pd.DataFrame.from_records(batch)
batch.clear()
if batch:
yield pd.DataFrame.from_records(batch)



def fetch_df_in(engine: Engine, table: str, id_list: Sequence[int]) -> pd.DataFrame:
"""Если нужен единый DataFrame — аккуратно склеиваем поток."""
frames = list(stream_query_in(engine, table, id_list))
return pd.concat(frames, ignore_index=True) if frames else pd.DataFrame()

# Пример использования:
# big_ids = range(1, 2_000_000)
# for df_chunk in stream_query_in(engine, "orders", big_ids, chunk_rows=100_000):
# process(df_chunk) # обрабатываем пачками без OOM

# Бонус: многоколонночный IN (tuple IN) без ручной генерации SQL
def stream_query_tuple_in(engine: Engine, table: str, pairs: Sequence[Dict[str, Any]]):
"""
pairs: [{ "country":"US", "city":"NYC" }, ...]
SELECT * FROM table WHERE (country, city) IN ((:country_1,:city_1), ...)
"""
stm = text(f"""
SELECT * FROM {table}
WHERE (country, city) IN :keys
""").bindparams(bindparam("keys", expanding=True))

# Подготовим данные как кортежи
key_tuples = [(p["country"], p["city"]) for p in pairs]

with engine.connect() as conn:
for row in conn.execution_options(stream_results=True).execute(stm, {"keys": key_tuples}):
yield dict(row._mapping)

# Пример:
# pairs = [{"country":"US","city":"NYC"}, {"country":"JP","city":"TOKYO"}]
# for rec in stream_query_tuple_in(engine, "warehouses", pairs):
# ...
6👍4🔥2
🚀 dumper — простой CLI для резервного копирования баз данных

Что это?
dumper — это утилита командной строки для создания бэкапов разных СУБД (PostgreSQL, MySQL и др.) с гибкой настройкой подключения и хранения. Инструмент ориентирован на разработчиков и админов, которым нужны быстрые и надёжные бэкапы.

Ключевые возможности:
- Поддержка нескольких СУБД.
- Гибкая конфигурация источников и мест хранения.
- Простота использования прямо из терминала.

Почему стоит обратить внимание:
- Лёгкая альтернатива тяжёлым системам бэкапов.
- Ускоряет рабочий процесс админов и devops.
- Надёжный инструмент для production и pet-проектов.

👉 Репозиторий: github.com/elkirrs/dumper
🔥21👍1
🎮 Учим SQL через захватывающую аркадную игру

Разработчики замутили настоящий олдскульный
шедевр, который сделает из вас МАСТЕРА баз данных и точно не даст заскучать.

• Проходим уровни, собираем пазлы вместе с уткой DuckDB и прокачиваем SQL на максимум.
• Квесты, задачи, подсказки — всё как в настоящем приключении.
• Работает прямо в браузере и даже на телефоне.

Любые запросы к базам — щёлкаем как семечки 👉 https://dbquacks.com/.
5👍4🔥3
🆕 PDF Arranger — лёгкий и удобный инструмент для работы с PDF.

Возможности:
- Объединение и разделение файлов
- Поворот и обрезка страниц
- Перестановка и удаление страниц
- Интуитивный drag-and-drop интерфейс

💻 Доступен для Linux, Windows (включая портативную версию) и BSD.
Полностью опенсорс (GPL-3.0).

Идеален, если нужно быстро подготовить PDF к печати или презентации — без сложных настроек.

📌 GitHub

#PDF #opensource #Linux #devtools
Please open Telegram to view this post
VIEW IN TELEGRAM
👍32🔥2
👨‍🔧 CoreNN — база данных для работы с векторами и эмбеддингами в масштабе миллиардов, с сублинейным временем отклика на обычных серверах.

📌 Пример: поиск по 1 млрд эмбеддингов комментариев Reddit из индекса 4,8 ТБ на диске занимает всего 15 мс.

🔧 Ключевые особенности:
- Работает на дешёвых SSD/flash-накопителях, а не в дорогой DRAM → в 40–100 раз дешевле.
- Масштабирование: от 1 до 1 млрд векторов в одном индексе.
- Upsert и delete оптимизируют локальный граф, освобождают место и сохраняют скорость — без полной перестройки.
- Поддерживает параллельные запросы и обновления без блокировок.

🔗 https://github.com/wilsonzlin/CoreNN
🔥72👍2
💡 SQL-трюк: фильтрация по "первому в группе"

Часто нужно взять только первую запись из каждой группы (например, последние покупки клиентов).
Мало кто знает, что это можно сделать без подзапросов с помощью ROW_NUMBER().


SELECT *
FROM (
SELECT
customer_id,
order_id,
order_date,
ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date DESC) AS rn
FROM orders
) t
WHERE rn = 1;


🔎 Здесь ROW_NUMBER() нумерует строки внутри каждой группы customer_id.
rn = 1 оставляет только самую свежую запись по каждому клиенту.
👍17😁53🔥3