Delphi: Как агрегировать только записи в TClientDataset?

Мне нужно сделать несколько агрегатов, используя TClientdataset. В SQL эти агрегаты могут быть выполнены с помощью скрипта следующим образом:

Select Sum(column1) from table1 where Date_Column < Date_Value

Поскольку мне нужна большая скорость во время очень длинного процесса и очень медленной сети, я хочу использовать агрегаты в памяти вместо использования sql . Моя идея состоит в том, чтобы добавить агрегат в ClientDataset с помощью выражения, например:

Sum(column1)

И создайте индекс Date_Column, затем отфильтруйте набор данных клиента следующим образом:

myClientdataset.SetRang([value1],[value2]);

Я ожидал увидеть совокупный результат этого диапазона, но, к сожалению, агрегат игнорирует диапазон и продолжает давать результат всех записей!

Итак, мой вопрос: как я могу добиться этого в TClientdataset? Или у вас есть другая идея, как делать ранжированные агрегаты в памяти?

1 ответ

Решение

Может быть, эта ссылка будет полезна: группировка и агрегаты

Редактировать:

Я думаю, что у меня это есть, это заняло у меня довольно много времени, и это был неприятный опыт;)

Я сделал пример проекта.

Во-первых, агрегат без фильтрации:

Агрегировать без фильтрации

Во-вторых, совокупность после нажатия кнопки:

Агрегат с фильтрацией

Это тот эффект, который вы хотели?

Обратите внимание, что я не смог достичь этого эффекта с помощью SetRange(), вместо этого я использовал свойство Filter.

Как добиться:

  1. Создайте индекс для некоторого поля, GroupingLevel должен быть 0.
  2. Установите этот индекс как свойство TClientDataset.IndexName.
  3. Создайте агрегат с GroupingLevel = 0 и Expression наподобие SUM(YourFieldName), в моем случае это был SUM(Population).
  4. В свойстве IndexName напишите индекс, который вы создали.
  5. Установите агрегат на активный во время разработки (казалось, что он не работает во время выполнения).

Мой код после нажатия кнопки:

  cdsMain.Filter := 'Population <= 100';
  cdsMain.Filtered := True;
  if not VarIsNull(cdsMain.Aggregates[0].Value) then
    lblAggregatedPopulation.Caption := 'Aggregated population: ' + IntToStr(cdsMain.Aggregates[0].Value);

Обратите внимание, что в фильтре вы можете легко изменить условие для достижения того же результата, что и для SetRange. Однако я читал, что SetRange быстрее фильтрует данные.

Надеюсь, поможет:)

Другие вопросы по тегам