Data Science. SQL hub
По всем вопросам- @workakkk @itchannels_telegram - 🔥лучшие ит-каналы @ai_machinelearning_big_data - Machine learning @pythonl - Python @pythonlbooks- python книги📚 @datascienceiot - ml книги📚 РКН: https://vk.cc/cIi9vo #VRHSZ
Больше📈 Аналитический обзор Telegram-канала Data Science. SQL hub
Канал Data Science. SQL hub (@sqlhub) языкового сегмента Русский является активным участником. Сейчас сообщество объединяет 35 973 подписчиков, занимая 3 610 место в категории Технологии и приложения и 17 707 место в регионе Россия.
📊 Показатели аудитории и динамика
С момента создания невідомо проект демонстрирует стремительный рост, собрав аудиторию из 35 973 подписчиков.
Согласно последним данным от 31 августа, 2026, канал показывает стабильную активность. За последние 30 дней изменение числа участников составило 66, а за последние 24 часа — 19, при этом общий охват остаётся высоким.
- Статус верификации: Не верифицирован
- Уровень вовлечённости (ER): Средний показатель вовлечённости аудитории составляет 6.43%. В первые 24 часа после публикации контент обычно набирает 3.46% реакций от общего числа подписчиков.
- Охват публикаций: В среднем каждый пост получает 2 311 просмотров. В течение первых суток публикация набирает 1 243 просмотров.
- Реакции и взаимодействия: Аудитория активно поддерживает контент: среднее количество реакций на один пост — 10.
- Тематические интересы: Контент сосредоточен на ключевых темах, таких как sql, индекс, postgres, index, sqlite.
📝 Описание и контентная политика
Автор описывает ресурс как площадку для выражения субъективного мнения:
“По всем вопросам- @workakkk
@itchannels_telegram - 🔥лучшие ит-каналы
@ai_machinelearning_big_data - Machine learning
@pythonl - Python
@pythonlbooks- python книги📚
@datascienceiot - ml книги📚
РКН: https://vk.cc/cIi9vo
#VRHSZ”
Благодаря высокой частоте обновлений (последние данные получены 01 сентября, 2026) канал поддерживает актуальность и высокий уровень охвата публикаций. Аналитика показывает, что аудитория активно взаимодействует с контентом, что делает его важной точкой влияния в категории Технологии и приложения.
orders со следующими полями:
orders(id, customer_id, order_date, amount)
📌 Задача:
Для каждого клиента (`customer_id`) найти наиболее поздний заказ (по order_date`), **не используя `GROUP BY и `MAX()`**.
🔥 Уловка: DISTINCT ON, TOP 1 WITH TIES и RANK() нельзя — ты ограничен базовым SQL, работающим на большинстве СУБД.
💡 Подумай:
Как ты решишь эту задачу только с JOIN, WHERE и EXISTS?
📥 Ожидаемый результат:
```sql
customer_id | order_id | order_date | amount
------------|----------|------------|--------
1001 | 87 | 2024-12-01 | 320.00
1002 | 91 | 2024-12-05 | 175.00
...
```
🧩 Подсказка:
Можно использовать NOT EXISTS, чтобы выбрать заказы, у которых нет более новых у того же клиента.
SELECT o.*
FROM orders o
WHERE NOT EXISTS (
SELECT 1
FROM orders o2
WHERE o2.customer_id = o.customer_id
AND o2.order_date > o.order_date
)
📎 Такой приём полезен:
• Когда нельзя использовать оконные функции
• Когда ты работаешь на старых версиях СУБД
• Когда нужна универсальность между MySQL / Oracle / SQLite
#SQL #Задача #БазыДанных #DataEngineering #Оптимизация
@sqlhubReader: разбирает новое письмо
- Memory Retriever: ищет релевантные воспоминания
- Planner: решает, что делать
- Executor: выполняет действия (ответ, событие и т.д.)
- Reflector: обновляет размышления агента
- Memory:
- Используется ChromaDB (векторная база), куда сохраняются ключевые сообщения, решения, действия и мысли.
- Tools:
- Встроенные функции-агенты (tools) для генерации писем, событий, напоминаний, оповещений и т.п.
- Всё вызывается динамически через LLM, как в OpenAI function calling.
🔁 Как агент работает на практике?
Пример цикла:
1. Приходит e-mail → Reader извлекает суть.
2. Memory Retriever ищет похожие прошлые переписки.
3. Planner решает: ответить? создать задачу? проигнорировать?
4. Executor выполняет нужное действие.
5. Reflector обновляет память и размышления.
Следующее письмо будет уже обрабатываться с учётом прошлого контекста. Агент понимает цепочку, тему, задачи и автоматически действует.
💡 Что делает ART особенным?
✅ Работает в несколько итераций, не просто «prompt → response»
✅ Помнит прошлые письма, решения, даже ошибки
✅ Сам планирует, что делать: отвечать, пересылать, напоминать
✅ Обновляет свои действия при изменении входных данных
✅ Настраивается под любые задачи: продажи, саппорт, личные письма, менеджмент
📎 Полный разбор от OpenPipe с примерами кода, схемами и демонстрацией:
👉 https://openpipe.ai/blog/art-e-mail-agent
Если ты хочешь строить LLM-агентов с настоящей памятью и логикой — это must-read. Это шаг к настоящим автономным ассистентам.
#AI #LLM #autonomousagents #LangGraph #e-mail #productivity #openpipe #инструменты
@sqlhubcontentless-delete для таблиц FTS5 — меньше места, выше скорость
- Новый флаг SQLITE_DBCONFIG_STMT_SCANSTATUS — можно отключать сбор статистики по выполнению запросов
- Оптимизации для LEFT JOIN + OR условий в WHERE — запросы выполняются заметно быстрее
- Улучшено поведение WITHOUT ROWID таблиц с составными ключами
🧪 Расширенные тесты:
- SQLite теперь использует дополнительный fuzzing для анализа стабильности ядра при высоких нагрузках и необычных SQL
🧹 Также исправлены:
- Ошибки в индексах при сложной комбинации JOIN + USING
- Утечка памяти при специфическом использовании PRAGMA function_list
💡 SQLite остаётся одной из самых лёгких, надёжных и удобных баз данных, которую можно использовать буквально везде: от браузеров и мобильных приложений до IoT и CLI-утилит.
📚 Полный список изменений — здесь:
https://www.sqlite.org/changes.html
@sqlhubsales:
CREATE TABLE sales (
id SERIAL PRIMARY KEY,
seller_name VARCHAR,
sale_amount NUMERIC,
sale_date DATE
);
📌 Задача:
Найди имя продавца, который заработал максимальную сумму за каждый месяц.
🧠 Подвох:
Многие пытаются использовать GROUP BY month, seller_name и MAX(), но это не даст имя продавца — только сумму. Нужно вернуть имя лучшего продавца за месяц. А если таких несколько? Тоже учти.
💡 Подсказки:
• Сначала сгруппируй продажи по month и seller_name
• Посчитай SUM(sale_amount)
• Используй оконную функцию RANK() или ROW_NUMBER()
• Отфильтруй только те строки, где rank = 1
🧩 Решение:
WITH monthly_totals AS (
SELECT
DATE_TRUNC('month', sale_date) AS month,
seller_name,
SUM(sale_amount) AS total
FROM sales
GROUP BY 1, 2
),
ranked AS (
SELECT *,
RANK() OVER (PARTITION BY month ORDER BY total DESC) AS rnk
FROM monthly_totals
)
SELECT month, seller_name, total
FROM ranked
WHERE rnk = 1
ORDER BY month;
👀 Бонус-вопрос:
Что будет, если у двух продавцов одинаковая сумма за месяц?
Какой оконной функцией это корректно учесть?
👉 RANK() вернёт обоих, ROW_NUMBER() — только одного.
📌 Отличная задача, чтобы проверить знание оконных функций и работы с агрегацией в SQL.
@sqlhub
CREATE TABLE office_logs (
employee_id INT,
team_id INT,
entry_time TIMESTAMP
);
Пример данных:
| employee_id | team_id | entry_time |
|-------------|---------|---------------------|
| 1 | 10 | 2024-01-01 08:59:10 |
| 2 | 10 | 2024-01-01 09:00:50 |
| 3 | 10 | 2024-01-01 09:02:20 |
| 4 | 20 | 2024-01-01 09:03:00 |
| 5 | 20 | 2024-01-01 09:04:40 |
| 6 | 20 | 2024-01-01 09:10:00 |
🎯 Задача
Напиши SQL-запрос, который определяет реально опоздавших сотрудников, если:
1. Время входа позже 09:00:00
2. Они не шли следом за коллегой из своей команды (разница входа больше 2 минут)
3. Один и тот же сотрудник не может быть "оправдан" несколькими — ищем только ближайшего предыдущего по времени из своей команды
💡 Подсказка: тут нужны:
- оконные функции (`LAG`)
- фильтрация по team_id
- расчёт интервалов времени
- доп. условия на время и порядок
Реальное мышление аналитика начинается там, где бизнес-логика важнее простых фильтров.
✅ Решение:
```sql
WITH logs_with_prev AS (
SELECT
employee_id,
team_id,
entry_time,
LAG(entry_time) OVER (
PARTITION BY team_id
ORDER BY entry_time
) AS prev_entry_time
FROM office_logs
),
marked_late AS (
SELECT
*,
EXTRACT(EPOCH FROM (entry_time - prev_entry_time)) AS seconds_diff
FROM logs_with_prev
)
SELECT
employee_id,
team_id,
entry_time
FROM marked_late
WHERE
entry_time::time > '09:00:00'
AND (
prev_entry_time IS NULL
OR EXTRACT(EPOCH FROM (entry_time - prev_entry_time)) > 120
);
```
🔍 **Что происходит:**
• Сначала `LAG` находит предыдущего входившего из той же команды
• Затем считаем, сколько секунд прошло между входами
• Если прошло больше 2 минут или сотрудник был первым — он **реально опоздал**
📦 Такое решение пригодится, если нужно учитывать **контекст** и **временные связи**, а не просто жёсткие фильтры.
@sqlhubsales:
CREATE TABLE sales (
salesman_id NUMBER,
region VARCHAR2(50),
amount NUMBER
);
📦 Данные:
| salesman_id | region | amount |
|-------------|------------|--------|
| 101 | 'North' | 200 |
| 101 | 'North' | NULL |
| 102 | 'North' | 150 |
| 103 | 'North' | NULL |
| 104 | 'South' | 300 |
| 105 | 'South' | NULL |
| 106 | 'South' | 50 |
| 107 | 'South' | NULL |
🎯 Задача 2.0:
Вывести salesman_id, чья сумма продаж меньше медианы по региону,
и показать ранг продавца внутри региона по сумме продаж, где NULL = 0.
⚠ Подвохи:
- MEDIAN() доступен только в Oracle.
- Нужно предварительно агрегировать суммы.
- Продавцы с только NULL-продажами = 0.
- Ранг должен учитывать правильную сортировку и связи с регионом.
✅ Решение:
```sql
WITH sales_total AS (
SELECT
salesman_id,
region,
NVL(SUM(amount), 0) AS total_sales
FROM sales
GROUP BY salesman_id, region
),
region_median AS (
SELECT
region,
MEDIAN(total_sales) AS region_median
FROM sales_total
GROUP BY region
),
ranked AS (
SELECT
st.salesman_id,
st.region,
st.total_sales,
r.region_median,
RANK() OVER (PARTITION BY st.region ORDER BY st.total_sales DESC) AS sales_rank
FROM sales_total st
JOIN region_median r ON st.region = r.region
)
SELECT *
FROM ranked
WHERE total_sales < region_median;
```
🧠 Объяснение:
1. `sales_total`: агрегируем продажи по продавцу, `NULL → 0`
2. `region_median`: считаем **медиану** продаж по каждому региону
3. `ranked`: добавляем `RANK()` по убыванию продаж внутри региона
4. Финальный фильтр: продажи ниже медианы
🔍 Пример вывода:
| salesman_id | region | total_sales | region_median | sales_rank |
|-------------|--------|-------------|----------------|-------------|
| 105 | South | 0 | 50 | 3 |
| 107 | South | 0 | 50 | 3 |
| 103 | North | 0 | 150 | 3 |
📌 Польза:
✅ Отлично проверяет:
- знание оконных функций
- работу с медианой
- поведение `NULL` в агрегатах
- построение CTE-цепочек и аналитики
🔁 Можно расширить:
- Добавить ранги *по убыванию и по возрастанию*
- Вместо `MEDIAN()` использовать `PERCENTILE_CONT()`
- Построить дэшборд: кто всегда "ниже медианы" за месяц
@sqlhub
w := varmq.NewVoidWorker(func(data any) {
// обработка задачи
}, 2)
q := w.BindQueue()
• С SQLite-поддержкой:
import "github.com/goptics/sqliteq"
db := sqliteq.New("test.db")
pq, _ := db.NewQueue("orders")
q := w.WithPersistentQueue(pq)
• С Redis (для распределённой обработки):
import "github.com/goptics/redisq"
rdb := redisq.New("redis://localhost:6379")
pq := rdb.NewDistributedQueue("transactions")
q := w.WithDistributedQueue(pq)
В итоге воркер обрабатывает задачи одинаково — независимо от хранилища.
✅ Почему это круто
• Гибкость: адаптеры позволяют легко менять хранилище без правок воркера
• Минимальные зависимости: в яд
📌 Читать