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.
Как добиться:
- Создайте индекс для некоторого поля, GroupingLevel должен быть 0.
- Установите этот индекс как свойство TClientDataset.IndexName.
- Создайте агрегат с GroupingLevel = 0 и Expression наподобие SUM(YourFieldName), в моем случае это был SUM(Population).
- В свойстве IndexName напишите индекс, который вы создали.
- Установите агрегат на активный во время разработки (казалось, что он не работает во время выполнения).
Мой код после нажатия кнопки:
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 быстрее фильтрует данные.
Надеюсь, поможет:)