Удаление последовательных дубликатов в базе данных postgresql, где данные находятся в столбце json - PullRequest
0 голосов
/ 31 октября 2018

Итак, у меня есть таблица postgresql с именем state_data, в которой есть два столбца: datetime и state. Столбец state имеет тип jsonb и определяет различные данные о состоянии для заданной даты и времени. Вот пример таблицы:

datetime            | state
================================================
2018-10-31 08:00:00 | {"temp":75.0,"location":1}
2018-10-31 08:01:00 | {"temp":75.0,"location":1}
2018-10-31 08:02:00 | {"temp":75.0,"location":1}
2018-10-31 08:03:00 | {"temp":75.0,"location":2}
2018-10-31 08:04:00 | {"temp":74.8,"location":1}
2018-10-31 08:05:00 | {"temp":74.8,"location":2}
2018-10-31 08:06:00 | {"temp":74.7,"location":1}

Со временем эта таблица станет очень большой - особенно я увеличу частоту дискретизации - и я действительно хочу хранить данные только там, где у последовательных строк разная температура. Таким образом, приведенная выше таблица снизится до

datetime            | state
================================================
2018-10-31 08:00:00 | {"temp":75.0,"location":1}
2018-10-31 08:04:00 | {"temp":74.8,"location":1}
2018-10-31 08:06:00 | {"temp":74.7,"location":1}

Я знаю, как это сделать, если данные о температуре находились в своем собственном столбце, но есть ли простой способ обработать эту операцию и удалить все последовательные дубликаты, основанные на элементе в столбце json?

Что если я захочу удалить дубликаты для обоих элементов json? Например,

datetime            | state
================================================
2018-10-31 08:00:00 | {"temp":75.0,"location":1}
2018-10-31 08:03:00 | {"temp":75.0,"location":2}
2018-10-31 08:04:00 | {"temp":74.8,"location":1}
2018-10-31 08:05:00 | {"temp":74.8,"location":2}
2018-10-31 08:06:00 | {"temp":74.7,"location":1}

1 Ответ

0 голосов
/ 31 октября 2018

Использовать оконную функцию lag():

select datetime, state
from (
    select datetime, state, lag(state) over (order by datetime) as prev
    from state_data
    ) s
where state->>'temp' is distinct from prev->>'temp'

Если у таблицы есть первичный ключ, вы должны использовать его в команде удаления. В отсутствие первичного ключа вы можете привести state к jsonb:

delete from state_data
where (datetime, state::jsonb) not in (
    select datetime, state::jsonb
    from (
        select datetime, state, lag(state) over (order by datetime) as prev
        from state_data
        ) s
    where state->>'temp' is distinct from prev->>'temp'
)
...