Перейти к основному содержанию
Перейти к основному содержанию

minSimpleState

Описание

Комбинатор 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 для объединения частичных агрегатных состояний.

См. также