Данная статья посвящена калькулируемым полям и полям агрегации. Она основана на официальной документации.
Калькулируемые поля это виртуальные поля, значения которых не получаются из БД и не хранятся в ней. Напротив, они калькулируются на клиентской стороне. FireDAC поддерживает калькулируемые поля всех TField.FieldKind типов
fkCalculated – это простое калькулируемое поле. Значение рассчитывается в обработчике TDataSet.OnCalcFields.
fkInternalCalc – это расширенное калькулируемое поле. Значение может быть ассоциировано с регулярными полями и хранится в кэше множества. Значение рассчитывается в обработчике TDataSet.OnCalcFields или через использование TField.DefaultExpression
fkLookup – это поле подстановки. Значение калькулируется автоматически, обеспечивая значение из подстановочного множества для ключевого значения из множества.
fkAggregate – это агрегируемое кальк. поле. Значение калькулируется используя TAggregateField.Expression, здесь используются функции COUNT, SUM, MIN, MAX, AVG
Только fkInternalCalc и fkAggregate поля могут быть использованы для фильтрации, сортировки, поиска.Также они хранятся с другими полями в “постоянных” потоках или файлах. Калькулируемые значения не могут сохраняться в базе автоматически.
TFDTable не поддерживает агрегированных полей в режиме ” live data window”
Стандартные калькулируемые поля
Поля fkCalculated и fkInternalCalc могут быть обработаны событием TDataSet.OnCalcFields
-в дезайн-тайм, используя Fields Editor
-в ран-тайм, далее приводится пример ран-тайма,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
procedure TForm1.Form1CalcFields(ADataSet: TDataSet); begin ADataSet.FieldByName('UName').AsString := UpperCase(ADataSet.FieldByName('Name').AsString); end; var oField: TField; i: Integer; ... FDQuery1.FieldDefs.Updated := False; FDQuery1.FieldDefs.Update; for i := 0 to FDQuery1.FieldDefs.Count - 1 do FDQuery1.FieldDefs[i].CreateField(Self); oField := TStringField.Create(FDQuery1); oField.Size := 50; oField.FieldName := 'UName'; oField.FieldKind := fkInternalCalc; // or fkCalculated oField.DataSet := FDQuery1; FDQuery1.OnCalcFields := Form1CalcFields; FDQuery1.Open; |
Expression Calculated Fields
Поля fiInternalCalc могут калькулироваться автоматически, используя так называемые “выражения” или expressions, определяемых TField.DefaultExpression. В этом случае внешний обработчик, такой как TDataSet.OnCalcFields не нужен. Выражение (expression) не может быть изменено когда множество активно. Например
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
var oField: TField; i: Integer; ... FDQuery1.FieldDefs.Updated := False; FDQuery1.FieldDefs.Update; for i := 0 to FDQuery1.FieldDefs.Count - 1 do FDQuery1.FieldDefs[i].CreateField(Self); oField := TStringField.Create(FDQuery1); oField.Size := 50; oField.FieldName := 'UName'; oField.FieldKind := fkInternalCalc; oField.DefaultExpression := 'UPPER(Name)'; oField.DataSet := FDQuery1; FDQuery1.Open; |
Агрегированные поля (Aggregated Fields)
Поля fkAggregate похожи на поля “выражений”. FireDAC калькулирует поля когда свойство TFDDataSet.AggregatesActive поставлено в True (по умолчанию оно в False). Агрегированное выражение не может быть изменено, когда множество активно. Например, чтобы создать агрегированное поле, можно использовать следующий код
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
var oField: TAggregateField; i: Integer; ... FDQuery1.FieldDefs.Updated := False; FDQuery1.FieldDefs.Update; for i := 0 to FDQuery1.FieldDefs.Count - 1 do FDQuery1.FieldDefs[i].CreateField(Self); oField := TAggregateField.Create(FDQuery1); oField.FieldName := 'Total'; oField.Expression := 'SUM((ItemPrice + ItemTaxes) * ItemCount)'; oField.DataSet := FDQuery1; FDQuery1.AggregatesActive := True; FDQuery1.Open; |
Агрегированные поля могут использовать группировку. В этом случае значение рассчитывается для записей с одним и тем же индексом, вместо всех записей. Чтобы определить группировку, можно использовать следующее
-Установить свойство TAggregateField.IndexName. По умолчанию используется текущий индекс.
-Установить уровень группировки TAggregateField.GroupingLevel. По умолчанию, это значение равно нулю.
Агрегированные поля поля всегда возвращают Null когда множество в состоянии dsInsert
Агрегированные значения (Aggregated Values)
Также FireDAC приложения могут использовать TFDDataSet.Aggregates чтобы определять агрегированные значения. Они более легкие, и могут быть определены в любое время, включая тот момент, когда множество активно.
Пример
1 2 3 4 5 6 7 8 |
with FDQuery1.Aggregates.Add do begin Name := 'Total'; Expression := 'SUM((ItemPrice + ItemTaxes) * ItemCount)'; Active := True; end; FDQuery1.AggregatesActive := True; ... Label1.Caption := VarToStr(FDQuery1.Aggregates[0].Value); |