Динамический выбор столбцов — это мощная, но недостаточно широко используемая функция ClickHouse, которая позволяет выбирать столбцы с помощью регулярных выражений вместо явного указания каждого столбца. Вы также можете применять функции к столбцам, подходящим по регулярному выражению, с помощью модификатора APPLY, что делает её чрезвычайно полезной для задач анализа и преобразования данных.
Начнём с распространённого сценария: выберем только те столбцы из набора данных NYC Taxi, в имени которых содержится _amount. Вместо того чтобы вручную вводить каждое имя столбца, мы можем использовать выражение COLUMNS с регулярным выражением:
FROM nyc_taxi.trips
SELECT COLUMNS('.*_amount')
LIMIT 10;
Этот запрос возвращает первые 10 строк, но только для столбцов, имена которых совпадают с шаблоном .*_amount (любые символы, после которых следует «_amount»).
Мы также можем использовать модификатор APPLY, чтобы применять функции сразу ко всем столбцам.
Например, если мы хотим найти максимальное значение для каждого из этих столбцов, можно выполнить следующий запрос:
SELECT COLUMNS('.*_amount|fee|tax') APPLY(max)
FROM nyc_taxi.trips;
Эти значения содержат много знаков после запятой, но, к счастью, мы можем это исправить, объединив вызовы функций в цепочку. В данном случае мы применим функцию avg, а затем функцию round:
SELECT COLUMNS('.*_amount|fee|tax') APPLY(avg) APPLY(round)
FROM nyc_taxi.trips;
Но это округляет средние значения до целых чисел. Если мы хотим округлить, скажем, до 2 знаков после запятой, мы тоже можем это сделать. Помимо функций, модификатор APPLY принимает лямбда-выражение, что дает нам гибкость и позволяет округлять средние значения до 2 знаков после запятой:
SELECT COLUMNS('.*_amount|fee|tax') APPLY(avg) APPLY(x -> round(x, 2))
FROM nyc_taxi.trips;
Пока всё хорошо. Но предположим, что нам нужно изменить одно из значений, оставив остальные без изменений. Например, возможно, мы хотим удвоить итоговую сумму и разделить налог MTA на 1.1. Мы можем сделать это с помощью модификатора REPLACE, который заменит один столбец, не затрагивая остальные.
FROM nyc_taxi.trips
SELECT
COLUMNS('.*_amount|fee|tax')
REPLACE(
total_amount*2 AS total_amount,
mta_tax/1.1 AS mta_tax
)
APPLY(avg)
APPLY(col -> round(col, 2));