Описание
Комбинатор SimpleState может быть применён к функции min
для получения минимального значения по всем входным значениям. Он возвращает
результат типа SimpleAggregateFunction.
Пример использования
Рассмотрим практический пример с таблицей, в которой хранятся ежедневные
измерения температуры. Для каждой точки измерения нам нужно хранить
наименьшую зафиксированную температуру. Использование типа
SimpleAggregateFunction с min автоматически обновляет хранимое значение,
когда встречается более низкая температура.
Создайте исходную таблицу для сырых измерений температуры:
CREATE TABLE raw_temperature_readings
(
location_id UInt32,
location_name String,
temperature Int32,
recorded_at DateTime DEFAULT now()
)
ENGINE = MergeTree()
ORDER BY (location_id, recorded_at);
Создайте агрегирующую таблицу для хранения минимальных температур:
CREATE TABLE temperature_extremes
(
location_id UInt32,
location_name String,
min_temp SimpleAggregateFunction(min, Int32), -- Хранит минимальную температуру
max_temp SimpleAggregateFunction(max, Int32) -- Хранит максимальную температуру
)
ENGINE = AggregatingMergeTree()
ORDER BY location_id;
Создайте инкрементальное материализованное представление, которое будет действовать как триггер вставки
для вставляемых данных и поддерживать актуальные минимальные и максимальные значения температур для каждого местоположения.
CREATE MATERIALIZED VIEW temperature_extremes_mv
TO temperature_extremes
AS SELECT
location_id,
location_name,
minSimpleState(temperature) AS min_temp, -- Используется комбинатор SimpleState
maxSimpleState(temperature) AS max_temp -- Используется комбинатор SimpleState
FROM raw_temperature_readings
GROUP BY location_id, location_name;
Добавьте несколько начальных значений температуры:
INSERT INTO raw_temperature_readings (location_id, location_name, temperature) VALUES
(1, 'Север', 5),
(2, 'Юг', 15),
(3, 'Запад', 10),
(4, 'Восток', 8);
Эти данные автоматически обрабатываются материализованным представлением. Проверим
текущее состояние:
SELECT
location_id,
location_name,
min_temp, -- Прямой доступ к значениям SimpleAggregateFunction
max_temp -- Функция финализации не нужна при использовании SimpleAggregateFunction
FROM temperature_extremes
ORDER BY location_id;
┌─location_id─┬─location_name─┬─min_temp─┬─max_temp─┐
│ 1 │ Север │ 5 │ 5 │
│ 2 │ Юг │ 15 │ 15 │
│ 3 │ Запад │ 10 │ 10 │
│ 4 │ Восток │ 8 │ 8 │
└─────────────┴───────────────┴──────────┴──────────┘
Добавьте ещё данные:
INSERT INTO raw_temperature_readings (location_id, location_name, temperature) VALUES
(1, 'Север', 3),
(2, 'Юг', 18),
(3, 'Запад', 10),
(1, 'Север', 8),
(4, 'Восток', 2);
Просмотрите обновлённые экстремумы после поступления новых данных:
SELECT
location_id,
location_name,
min_temp,
max_temp
FROM temperature_extremes
ORDER BY location_id;
┌─location_id─┬─location_name─┬─min_temp─┬─max_temp─┐
│ 1 │ Север │ 3 │ 8 │
│ 1 │ Север │ 5 │ 5 │
│ 2 │ Юг │ 18 │ 18 │
│ 2 │ Юг │ 15 │ 15 │
│ 3 │ Запад │ 10 │ 10 │
│ 3 │ Запад │ 10 │ 10 │
│ 4 │ Восток │ 2 │ 2 │
│ 4 │ Восток │ 8 │ 8 │
└─────────────┴───────────────┴──────────┴──────────┘
Обратите внимание, что выше для каждой локации у нас по два вставленных значения. Это связано с тем, что части еще не были объединены (и агрегированы с помощью AggregatingMergeTree). Чтобы получить итоговый результат из частичных состояний, нужно добавить GROUP BY:
SELECT
location_id,
location_name,
min(min_temp) AS min_temp, -- Агрегирование по всем партам
max(max_temp) AS max_temp -- Агрегирование по всем партам
FROM temperature_extremes
GROUP BY location_id, location_name
ORDER BY location_id;
Теперь мы видим ожидаемый результат:
┌─location_id─┬─location_name─┬─min_temp─┬─max_temp─┐
│ 1 │ Север │ 3 │ 8 │
│ 2 │ Юг │ 15 │ 18 │
│ 3 │ Запад │ 10 │ 10 │
│ 4 │ Восток │ 2 │ 8 │
└─────────────┴───────────────┴──────────┴──────────┘
Примечание
С SimpleState вам не нужно использовать комбинатор Merge для объединения
частичных агрегатных состояний.
См. также