🧠 Почему в ClickHouse функции — это часть архитектуры запроса
🔥 Главная мысль
В ClickHouse функции — это не просто “дополнение к SQL”.
Очень часто именно функции определяют, насколько запрос будет:
• удобным • выразительным • быстрым • подходящим под аналитическую задачу
Если сказать совсем просто:
в ClickHouse функции — это один из главных рабочих инструментов аналитика и инженера.
И тут важно понимать, что функции бывают разными:
• регулярные • агрегатные • оконные • табличные • UDF-функции
То есть мир функций в ClickHouse шире, чем просто lower(), sum() или toDate().
🟢 Плюсы:
• можно очень гибко обрабатывать данные прямо в запросе • удобно работать со строками, массивами, датами и числами • агрегатные функции сильно усиливают аналитику • есть табличные и оконные функции для более сложных сценариев • есть UDF, если стандартных функций уже не хватает
Пример плюса: если тебе нужно из массива вытащить только нужные элементы, сразу отфильтровать их и потом агрегировать, это можно сделать прямо в запросе без отдельного ETL-шага.
🔴 Минусы:
• новички часто путают типы функций • без понимания агрегации легко написать неправильный запрос • оконные функции и arrayJoin часто ведут себя не так, как ожидают сначала • UDF дают гибкость, но усложняют поддержку • при избытке логики в SQL запросы становятся тяжелее для чтения
Пример минуса: человек видит функцию и пытается использовать её “как в обычной строке”, а на деле это уже агрегатная или оконная логика, и запрос либо падает, либо даёт неожиданный результат.
🧪 Живые примеры
- Регулярные функции
Они работают на уровне одной строки.
Например:
• lower() • upper() • trim() • toDate() • toStartOfHour() • arrayMap()
То есть: на входе одна строка → на выходе результат для этой же строки.
Пример: если в столбце event_time лежит timestamp, то через toDate(event_time) ты получишь дату для каждой строки.
- Агрегатные функции
Они работают уже на группе строк.
Например:
• sum() • avg() • count() • uniq() • argMax() • quantile()
То есть: на входе несколько строк → на выходе один агрегированный результат.
Пример: если сделать
sum(amount) GROUP BY user_id
то ты получишь одну сумму на каждого пользователя, а не результат по каждой строке отдельно.
- arrayJoin
Это особый случай.
Он не регулярный и не агрегатный. Он превращает одну строку в несколько строк по элементам массива.
Пример: если у тебя есть строка с массивом:
['sql', 'clickhouse', 'bi']
то arrayJoin(tags) развернёт её в 3 отдельные строки.
Это очень мощно, но именно здесь новички часто удивляются, почему строк вдруг стало больше.
- Табличные функции
Табличная функция — это функция, которая возвращает набор строк и может использоваться как источник данных в FROM
Примеры:
• numbers(10) • generateRandom() • url(...) • s3(...) • file(...)
Пример: если написать
SELECT * FROM numbers(5)
то ClickHouse сам сгенерирует 5 строк с числами
То есть табличная функция — это уже не “обработка значения”, а источник данных прямо внутри запроса
Это очень удобно для:
• тестов • генерации данных • чтения внешних источников • быстрых технических проверок
- Оконные функции
Оконная функция — это когда ты считаешь что-то по набору строк вокруг текущей строки, но при этом не схлопываешь результат в одну строку на группу
Примеры:
• row_number() • rank() • dense_rank() • sum() over (...) • avg() over (...) • lag() • lead()
Пример: если написать
row_number() over (partition by user_id order by event_time)
то ты получишь номер события внутри каждого пользователя
А если написать
sum(amount) over (partition by user_id order by event_time)
то ты получишь накопительную сумму по пользователю, не теряя строки
Это очень важно, потому что оконные функции позволяют анализировать последовательность событий, не сворачивая данные через GROUP BY
🏗 Архитектурная мысль
В больших компаниях функции в ClickHouse используют не “для красоты”, а чтобы сократить количество лишних этапов в пайплайне
Например:
• часть преобразований делать прямо в SQL • работать с массивами без отдельной распаковки вне БД • считать