Android - простой/эффективный способ сохранить кумулятивную сумму для столбца SQLite

Каков наилучший способ сохранить «кумулятивную сумму» определенного столбца данных в SQLite? Я нашел несколько примеров в Интернете, но я не уверен на 100%, как я могу интегрировать эти подходы в свой ContentProvider.

В предыдущих приложениях я пытался самостоятельно поддерживать совокупные данные, обновляя данные каждый раз, когда вставляю новые данные в таблицу. Например, в приведенном ниже примере кода каждый раз, когда я добавляю новую запись со значением score, я вручную обновляю значение cumulative_score на основе его значения в предыдущей строке.

_id   score   cumulative_score
1     100     100
2     50      150
3     25      175
4     25      200
5     10      210

Однако это далеко не идеально и становится очень запутанным при работе с таблицами с большим количеством столбцов. Есть ли способ как-то автоматизировать процесс обновления совокупных данных каждый раз, когда я вставляю/обновляю записи в свою таблицу? Как я могу интегрировать это в свою реализацию ContentProvider?

Я знаю, что должен быть способ сделать это... Я просто не знаю, как это сделать. Спасибо!


person Alex Lockwood    schedule 15.03.2012    source источник


Ответы (1)


Вероятно, самый простой способ — с помощью триггера SQLite. Это самое близкое, что я знаю, к «автоматизации». Просто используйте триггер вставки, который берет предыдущую совокупную сумму, добавляет текущую оценку и сохраняет ее в совокупной сумме новой строки. Что-то вроде этого (при условии, что _id - это столбец, в котором вы заказываете):

CREATE TRIGGER calc_cumulative_score AFTER INSERT ON tablename FOR EACH ROW
BEGIN
    UPDATE tablename SET cumulative_score =
        (SELECT cumulative_score
         FROM tablename
         WHERE _id = (SELECT MAX(_id) FROM tablename))
        + new.score
    WHERE _id = new._id;
END

Убедитесь, что триггер и исходная вставка находятся в одной и той же транзакции. Для произвольных обновлений столбца score пришлось бы реализовывать рекурсивный триггер, который каким-то образом находит следующий наивысший id (возможно, выбирая по min id в наборе строк с id больше текущего) и обновляет его накопительная сумма.

Если вы против использования триггеров, вы можете сделать более или менее то же самое в ContentProvider в методах insert и update вручную, хотя, поскольку вы в значительной степени заблокированы в SQLite на Android, я не вижу особых причин не использовать триггеры.

Я предполагаю, что вы хотите сделать это как оптимизацию, так как в противном случае вы могли бы просто вычислить сумму по запросу (O(n) против O(1), поэтому вам придется учитывать, насколько большим может быть n и как часто вам нужны суммы).

person keitwb    schedule 15.04.2012