Delphi: Как агрегировать только записи в TClientDataset? - PullRequest
6 голосов
/ 06 июля 2011

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

Select Sum(column1) from table1 where Date_Column < Date_Value

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

Sum(column1)

и создать индекс Date_Column, а затем отфильтровать набор данных клиента так:

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

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

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

1 Ответ

8 голосов
/ 06 июля 2011

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

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

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

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

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

Aggregate without filtering

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

Aggregate with filtering

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

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

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

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

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

  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 быстрее фильтрует данные.

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

...