QGIS API Documentation 3.38.0-Grenoble (exported)
Loading...
Searching...
No Matches
qgsaggregatecalculator.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsaggregatecalculator.cpp
3 --------------------------
4 begin : May 2016
5 copyright : (C) 2016 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19#include "qgsexpressionutils.h"
20#include "qgsfeature.h"
21#include "qgsfeaturerequest.h"
22#include "qgsfeatureiterator.h"
23#include "qgsgeometry.h"
24#include "qgsvectorlayer.h"
28
29
31 : mLayer( layer )
32{
33
34}
35
37{
38 return mLayer;
39}
40
42{
43 mFilterExpression = parameters.filter;
44 mDelimiter = parameters.delimiter;
45 mOrderBy = parameters.orderBy;
46}
47
49{
50 mFidsSet = true;
51 mFidsFilter = fids;
52}
53
55 const QString &fieldOrExpression, QgsExpressionContext *context, bool *ok, QgsFeedback *feedback ) const
56{
57 mLastError.clear();
58 if ( ok )
59 *ok = false;
60
62
63 if ( !mLayer )
64 return QVariant();
65
66 QgsExpressionContext defaultContext = mLayer->createExpressionContext();
67 context = context ? context : &defaultContext;
68
69 std::unique_ptr<QgsExpression> expression;
70
71 const int attrNum = QgsExpression::expressionToLayerFieldIndex( fieldOrExpression, mLayer );
72 if ( attrNum == -1 )
73 {
74 Q_ASSERT( context );
75 context->setFields( mLayer->fields() );
76 // try to use expression
77 expression.reset( new QgsExpression( fieldOrExpression ) );
78
79 if ( expression->hasParserError() || !expression->prepare( context ) )
80 {
81 mLastError = !expression->parserErrorString().isEmpty() ? expression->parserErrorString() : expression->evalErrorString();
82 return QVariant();
83 }
84 }
85
86 QSet<QString> lst;
87 if ( !expression )
88 lst.insert( mLayer->fields().at( attrNum ).name() );
89 else
90 lst = expression->referencedColumns();
91
92 bool expressionNeedsGeometry { expression &&expression->needsGeometry() };
93
94 if ( !mOrderBy.empty() )
95 {
96 request.setOrderBy( mOrderBy );
97 for ( const QgsFeatureRequest::OrderByClause &orderBy : std::as_const( mOrderBy ) )
98 {
99 if ( orderBy.expression().needsGeometry() )
100 {
101 expressionNeedsGeometry = true;
102 break;
103 }
104 }
105 }
106
107 request.setFlags( expressionNeedsGeometry ?
110 .setSubsetOfAttributes( lst, mLayer->fields() );
111
112 if ( mFidsSet )
113 request.setFilterFids( mFidsFilter );
114
115 if ( !mFilterExpression.isEmpty() )
116 request.setFilterExpression( mFilterExpression );
117 if ( context )
118 request.setExpressionContext( *context );
119
120 request.setFeedback( feedback ? feedback : ( context ? context->feedback() : nullptr ) );
121
122 //determine result type
123 QMetaType::Type resultType = QMetaType::Type::Double;
124 int userType = 0;
125 if ( attrNum == -1 )
126 {
127 if ( aggregate == Qgis::Aggregate::GeometryCollect )
128 {
129 // in this case we know the result should be a geometry value, so no need to sniff it out...
130 resultType = QMetaType::Type::User;
131 }
132 else
133 {
134 // check expression result type
135 bool foundFeatures = false;
136 std::tuple<QMetaType::Type, int> returnType = QgsExpressionUtils::determineResultType( fieldOrExpression, mLayer, request, *context, &foundFeatures );
137 if ( !foundFeatures )
138 {
139 if ( ok )
140 *ok = true;
141 return defaultValue( aggregate );
142 }
143
144 resultType = std::get<0>( returnType );
145 userType = std::get<1>( returnType );
146 if ( resultType == QMetaType::Type::UnknownType )
147 {
148 QVariant v;
149 switch ( aggregate )
150 {
151 // string
156 v = QString();
157 break;
158
159 // numerical
169 // mixed type, fallback to numerical
177 v = 0.0;
178 break;
179
180 // geometry
182 v = QgsGeometry();
183 break;
184
185 // list, fallback to string
187 v = QString();
188 break;
189 }
190 resultType = static_cast<QMetaType::Type>( v.userType() );
191 userType = v.userType();
192 }
193 }
194 }
195 else
196 resultType = mLayer->fields().at( attrNum ).type();
197
198 QgsFeatureIterator fit = mLayer->getFeatures( request );
199 return calculate( aggregate, fit, resultType, userType, attrNum, expression.get(), mDelimiter, context, ok, &mLastError );
200}
201
203{
204 const QString normalized = string.trimmed().toLower();
205
206 if ( ok )
207 *ok = true;
208
209 if ( normalized == QLatin1String( "count" ) )
211 else if ( normalized == QLatin1String( "count_distinct" ) )
213 else if ( normalized == QLatin1String( "count_missing" ) )
215 else if ( normalized == QLatin1String( "min" ) || normalized == QLatin1String( "minimum" ) )
217 else if ( normalized == QLatin1String( "max" ) || normalized == QLatin1String( "maximum" ) )
219 else if ( normalized == QLatin1String( "sum" ) )
221 else if ( normalized == QLatin1String( "mean" ) )
223 else if ( normalized == QLatin1String( "median" ) )
225 else if ( normalized == QLatin1String( "stdev" ) )
227 else if ( normalized == QLatin1String( "stdevsample" ) )
229 else if ( normalized == QLatin1String( "range" ) )
231 else if ( normalized == QLatin1String( "minority" ) )
233 else if ( normalized == QLatin1String( "majority" ) )
235 else if ( normalized == QLatin1String( "q1" ) )
237 else if ( normalized == QLatin1String( "q3" ) )
239 else if ( normalized == QLatin1String( "iqr" ) )
241 else if ( normalized == QLatin1String( "min_length" ) )
243 else if ( normalized == QLatin1String( "max_length" ) )
245 else if ( normalized == QLatin1String( "concatenate" ) )
247 else if ( normalized == QLatin1String( "concatenate_unique" ) )
249 else if ( normalized == QLatin1String( "collect" ) )
251 else if ( normalized == QLatin1String( "array_agg" ) )
253
254 if ( ok )
255 *ok = false;
256
258}
259
261{
262 switch ( aggregate )
263 {
265 return QObject::tr( "count" );
267 return QObject::tr( "count distinct" );
269 return QObject::tr( "count missing" );
271 return QObject::tr( "minimum" );
273 return QObject::tr( "maximum" );
275 return QObject::tr( "sum" );
277 return QObject::tr( "mean" );
279 return QObject::tr( "median" );
281 return QObject::tr( "standard deviation" );
283 return QObject::tr( "standard deviation (sample)" );
285 return QObject::tr( "range" );
287 return QObject::tr( "minority" );
289 return QObject::tr( "majority" );
291 return QObject::tr( "first quartile" );
293 return QObject::tr( "third quartile" );
295 return QObject::tr( "inter quartile range" );
297 return QObject::tr( "minimum length" );
299 return QObject::tr( "maximum length" );
301 return QObject::tr( "concatenate" );
303 return QObject::tr( "collection" );
305 return QObject::tr( "array aggregate" );
307 return QObject::tr( "concatenate (unique)" );
308 }
309 return QString();
310}
311
312QList<QgsAggregateCalculator::AggregateInfo> QgsAggregateCalculator::aggregates()
313{
314 QList< AggregateInfo > aggregates;
317 {
318 QStringLiteral( "count" ),
319 QCoreApplication::tr( "Count" ),
320 QSet<QMetaType::Type>()
321 << QMetaType::Type::QDateTime
322 << QMetaType::Type::QDate
323 << QMetaType::Type::Int
324 << QMetaType::Type::UInt
325 << QMetaType::Type::LongLong
326 << QMetaType::Type::ULongLong
327 << QMetaType::Type::QString
328 }
330 {
331 QStringLiteral( "count_distinct" ),
332 QCoreApplication::tr( "Count Distinct" ),
333 QSet<QMetaType::Type>()
334 << QMetaType::Type::QDateTime
335 << QMetaType::Type::QDate
336 << QMetaType::Type::UInt
337 << QMetaType::Type::Int
338 << QMetaType::Type::LongLong
339 << QMetaType::Type::ULongLong
340 << QMetaType::Type::QString
341 }
343 {
344 QStringLiteral( "count_missing" ),
345 QCoreApplication::tr( "Count Missing" ),
346 QSet<QMetaType::Type>()
347 << QMetaType::Type::QDateTime
348 << QMetaType::Type::QDate
349 << QMetaType::Type::Int
350 << QMetaType::Type::UInt
351 << QMetaType::Type::LongLong
352 << QMetaType::Type::QString
353 }
355 {
356 QStringLiteral( "min" ),
357 QCoreApplication::tr( "Min" ),
358 QSet<QMetaType::Type>()
359 << QMetaType::Type::QDateTime
360 << QMetaType::Type::QDate
361 << QMetaType::Type::Int
362 << QMetaType::Type::UInt
363 << QMetaType::Type::LongLong
364 << QMetaType::Type::ULongLong
365 << QMetaType::Type::Double
366 << QMetaType::Type::QString
367 }
369 {
370 QStringLiteral( "max" ),
371 QCoreApplication::tr( "Max" ),
372 QSet<QMetaType::Type>()
373 << QMetaType::Type::QDateTime
374 << QMetaType::Type::QDate
375 << QMetaType::Type::Int
376 << QMetaType::Type::UInt
377 << QMetaType::Type::LongLong
378 << QMetaType::Type::ULongLong
379 << QMetaType::Type::Double
380 << QMetaType::Type::QString
381 }
383 {
384 QStringLiteral( "sum" ),
385 QCoreApplication::tr( "Sum" ),
386 QSet<QMetaType::Type>()
387 << QMetaType::Type::Int
388 << QMetaType::Type::UInt
389 << QMetaType::Type::LongLong
390 << QMetaType::Type::ULongLong
391 << QMetaType::Type::Double
392 }
394 {
395 QStringLiteral( "mean" ),
396 QCoreApplication::tr( "Mean" ),
397 QSet<QMetaType::Type>()
398 << QMetaType::Type::Int
399 << QMetaType::Type::UInt
400 << QMetaType::Type::LongLong
401 << QMetaType::Type::ULongLong
402 << QMetaType::Type::Double
403 }
405 {
406 QStringLiteral( "median" ),
407 QCoreApplication::tr( "Median" ),
408 QSet<QMetaType::Type>()
409 << QMetaType::Type::Int
410 << QMetaType::Type::UInt
411 << QMetaType::Type::Double
412 }
414 {
415 QStringLiteral( "stdev" ),
416 QCoreApplication::tr( "Stdev" ),
417 QSet<QMetaType::Type>()
418 << QMetaType::Type::Int
419 << QMetaType::Type::UInt
420 << QMetaType::Type::LongLong
421 << QMetaType::Type::ULongLong
422 << QMetaType::Type::Double
423 }
425 {
426 QStringLiteral( "stdevsample" ),
427 QCoreApplication::tr( "Stdev Sample" ),
428 QSet<QMetaType::Type>()
429 << QMetaType::Type::Int
430 << QMetaType::Type::UInt
431 << QMetaType::Type::LongLong
432 << QMetaType::Type::ULongLong
433 << QMetaType::Type::Double
434 }
436 {
437 QStringLiteral( "range" ),
438 QCoreApplication::tr( "Range" ),
439 QSet<QMetaType::Type>()
440 << QMetaType::Type::QDate
441 << QMetaType::Type::QDateTime
442 << QMetaType::Type::Int
443 << QMetaType::Type::UInt
444 << QMetaType::Type::LongLong
445 << QMetaType::Type::ULongLong
446 << QMetaType::Type::Double
447 }
449 {
450 QStringLiteral( "minority" ),
451 QCoreApplication::tr( "Minority" ),
452 QSet<QMetaType::Type>()
453 << QMetaType::Type::Int
454 << QMetaType::Type::UInt
455 << QMetaType::Type::LongLong
456 << QMetaType::Type::ULongLong
457 << QMetaType::Type::Double
458 << QMetaType::Type::QString
459 }
461 {
462 QStringLiteral( "majority" ),
463 QCoreApplication::tr( "Majority" ),
464 QSet<QMetaType::Type>()
465 << QMetaType::Type::Int
466 << QMetaType::Type::UInt
467 << QMetaType::Type::LongLong
468 << QMetaType::Type::ULongLong
469 << QMetaType::Type::Double
470 << QMetaType::Type::QString
471 }
473 {
474 QStringLiteral( "q1" ),
475 QCoreApplication::tr( "Q1" ),
476 QSet<QMetaType::Type>()
477 << QMetaType::Type::Int
478 << QMetaType::Type::UInt
479 << QMetaType::Type::LongLong
480 << QMetaType::Type::ULongLong
481 << QMetaType::Type::Double
482 }
484 {
485 QStringLiteral( "q3" ),
486 QCoreApplication::tr( "Q3" ),
487 QSet<QMetaType::Type>()
488 << QMetaType::Type::Int
489 << QMetaType::Type::UInt
490 << QMetaType::Type::LongLong
491 << QMetaType::Type::ULongLong
492 << QMetaType::Type::Double
493 }
495 {
496 QStringLiteral( "iqr" ),
497 QCoreApplication::tr( "InterQuartileRange" ),
498 QSet<QMetaType::Type>()
499 << QMetaType::Type::Int
500 << QMetaType::Type::UInt
501 << QMetaType::Type::LongLong
502 << QMetaType::Type::ULongLong
503 << QMetaType::Type::Double
504 }
506 {
507 QStringLiteral( "min_length" ),
508 QCoreApplication::tr( "Min Length" ),
509 QSet<QMetaType::Type>()
510 << QMetaType::Type::QString
511 }
513 {
514 QStringLiteral( "max_length" ),
515 QCoreApplication::tr( "Max Length" ),
516 QSet<QMetaType::Type>()
517 << QMetaType::Type::QString
518 }
520 {
521 QStringLiteral( "concatenate" ),
522 QCoreApplication::tr( "Concatenate" ),
523 QSet<QMetaType::Type>()
524 << QMetaType::Type::QString
525 }
527 {
528 QStringLiteral( "collect" ),
529 QCoreApplication::tr( "Collect" ),
530 QSet<QMetaType::Type>()
531 }
533 {
534 QStringLiteral( "array_agg" ),
535 QCoreApplication::tr( "Array Aggregate" ),
536 QSet<QMetaType::Type>()
537 };
538
539 return aggregates;
540}
541
542QVariant QgsAggregateCalculator::calculate( Qgis::Aggregate aggregate, QgsFeatureIterator &fit, QMetaType::Type resultType, int userType,
543 int attr, QgsExpression *expression, const QString &delimiter, QgsExpressionContext *context, bool *ok, QString *error )
544{
545 if ( ok )
546 *ok = false;
547
548 if ( aggregate == Qgis::Aggregate::ArrayAggregate )
549 {
550 if ( ok )
551 *ok = true;
552 return calculateArrayAggregate( fit, attr, expression, context );
553 }
554
555 switch ( resultType )
556 {
557 case QMetaType::Type::Int:
558 case QMetaType::Type::UInt:
559 case QMetaType::Type::LongLong:
560 case QMetaType::Type::ULongLong:
561 case QMetaType::Type::Double:
562 {
563 bool statOk = false;
564 const Qgis::Statistic stat = numericStatFromAggregate( aggregate, &statOk );
565 if ( !statOk )
566 {
567 if ( error )
568 *error = expression ? QObject::tr( "Cannot calculate %1 on numeric values" ).arg( displayName( aggregate ) )
569 : QObject::tr( "Cannot calculate %1 on numeric fields" ).arg( displayName( aggregate ) );
570 return QVariant();
571 }
572
573 if ( ok )
574 *ok = true;
575 return calculateNumericAggregate( fit, attr, expression, context, stat );
576 }
577
578 case QMetaType::Type::QDate:
579 case QMetaType::Type::QDateTime:
580 {
581 bool statOk = false;
582 const Qgis::DateTimeStatistic stat = dateTimeStatFromAggregate( aggregate, &statOk );
583 if ( !statOk )
584 {
585 if ( error )
586 *error = ( expression ? QObject::tr( "Cannot calculate %1 on %2 values" ).arg( displayName( aggregate ) ) :
587 QObject::tr( "Cannot calculate %1 on %2 fields" ).arg( displayName( aggregate ) ) ).arg( resultType == QMetaType::Type::QDate ? QObject::tr( "date" ) : QObject::tr( "datetime" ) );
588 return QVariant();
589 }
590
591 if ( ok )
592 *ok = true;
593 return calculateDateTimeAggregate( fit, attr, expression, context, stat );
594 }
595
596 case QMetaType::Type::User:
597 {
598 if ( aggregate == Qgis::Aggregate::GeometryCollect )
599 {
600 if ( ok )
601 *ok = true;
602 return calculateGeometryAggregate( fit, expression, context );
603 }
604 else
605 {
606 return QVariant();
607 }
608 }
609
610 default:
611 {
612 // treat as string
613 if ( aggregate == Qgis::Aggregate::StringConcatenate )
614 {
615 //special case
616 if ( ok )
617 *ok = true;
618 return concatenateStrings( fit, attr, expression, context, delimiter );
619 }
620 else if ( aggregate == Qgis::Aggregate::StringConcatenateUnique )
621 {
622 //special case
623 if ( ok )
624 *ok = true;
625 return concatenateStrings( fit, attr, expression, context, delimiter, true );
626 }
627
628 bool statOk = false;
629 const Qgis::StringStatistic stat = stringStatFromAggregate( aggregate, &statOk );
630 if ( !statOk )
631 {
632 QString typeString;
633 if ( resultType == QMetaType::Type::UnknownType )
634 typeString = QObject::tr( "null" );
635 else if ( resultType == QMetaType::Type::User )
636 typeString = QMetaType::typeName( userType );
637 else
638 typeString = resultType == QMetaType::Type::QString ? QObject::tr( "string" ) : QVariant::typeToName( resultType );
639
640 if ( error )
641 *error = expression ? QObject::tr( "Cannot calculate %1 on %3 values" ).arg( displayName( aggregate ), typeString )
642 : QObject::tr( "Cannot calculate %1 on %3 fields" ).arg( displayName( aggregate ), typeString );
643 return QVariant();
644 }
645
646 if ( ok )
647 *ok = true;
648 return calculateStringAggregate( fit, attr, expression, context, stat );
649 }
650 }
651
652#ifndef _MSC_VER
653 return QVariant();
654#endif
655}
656
657Qgis::Statistic QgsAggregateCalculator::numericStatFromAggregate( Qgis::Aggregate aggregate, bool *ok )
658{
659 if ( ok )
660 *ok = true;
661
662 switch ( aggregate )
663 {
702 {
703 if ( ok )
704 *ok = false;
706 }
707 }
708
709 if ( ok )
710 *ok = false;
712}
713
714Qgis::StringStatistic QgsAggregateCalculator::stringStatFromAggregate( Qgis::Aggregate aggregate, bool *ok )
715{
716 if ( ok )
717 *ok = true;
718
719 switch ( aggregate )
720 {
739
753 {
754 if ( ok )
755 *ok = false;
757 }
758 }
759
760 if ( ok )
761 *ok = false;
763}
764
765Qgis::DateTimeStatistic QgsAggregateCalculator::dateTimeStatFromAggregate( Qgis::Aggregate aggregate, bool *ok )
766{
767 if ( ok )
768 *ok = true;
769
770 switch ( aggregate )
771 {
784
801 {
802 if ( ok )
803 *ok = false;
805 }
806 }
807
808 if ( ok )
809 *ok = false;
811}
812
813QVariant QgsAggregateCalculator::calculateNumericAggregate( QgsFeatureIterator &fit, int attr, QgsExpression *expression,
815{
816 Q_ASSERT( expression || attr >= 0 );
817
818 QgsStatisticalSummary s( stat );
819 QgsFeature f;
820
821 while ( fit.nextFeature( f ) )
822 {
823 if ( expression )
824 {
825 Q_ASSERT( context );
826 context->setFeature( f );
827 const QVariant v = expression->evaluate( context );
828 s.addVariant( v );
829 }
830 else
831 {
832 s.addVariant( f.attribute( attr ) );
833 }
834 }
835 s.finalize();
836 const double val = s.statistic( stat );
837 return std::isnan( val ) ? QVariant() : val;
838}
839
840QVariant QgsAggregateCalculator::calculateStringAggregate( QgsFeatureIterator &fit, int attr, QgsExpression *expression,
842{
843 Q_ASSERT( expression || attr >= 0 );
844
846 QgsFeature f;
847
848 while ( fit.nextFeature( f ) )
849 {
850 if ( expression )
851 {
852 Q_ASSERT( context );
853 context->setFeature( f );
854 const QVariant v = expression->evaluate( context );
855 s.addValue( v );
856 }
857 else
858 {
859 s.addValue( f.attribute( attr ) );
860 }
861 }
862 s.finalize();
863 return s.statistic( stat );
864}
865
866QVariant QgsAggregateCalculator::calculateGeometryAggregate( QgsFeatureIterator &fit, QgsExpression *expression, QgsExpressionContext *context )
867{
868 Q_ASSERT( expression );
869
870 QgsFeature f;
871 QVector< QgsGeometry > geometries;
872 while ( fit.nextFeature( f ) )
873 {
874 Q_ASSERT( context );
875 context->setFeature( f );
876 const QVariant v = expression->evaluate( context );
877 if ( v.userType() == QMetaType::type( "QgsGeometry" ) )
878 {
879 geometries << v.value<QgsGeometry>();
880 }
881 }
882
883 return QVariant::fromValue( QgsGeometry::collectGeometry( geometries ) );
884}
885
886QVariant QgsAggregateCalculator::concatenateStrings( QgsFeatureIterator &fit, int attr, QgsExpression *expression,
887 QgsExpressionContext *context, const QString &delimiter, bool unique )
888{
889 Q_ASSERT( expression || attr >= 0 );
890
891 QgsFeature f;
892 QStringList results;
893 while ( fit.nextFeature( f ) )
894 {
895 QString result;
896 if ( expression )
897 {
898 Q_ASSERT( context );
899 context->setFeature( f );
900 const QVariant v = expression->evaluate( context );
901 result = v.toString();
902 }
903 else
904 {
905 result = f.attribute( attr ).toString();
906 }
907
908 if ( !unique || !results.contains( result ) )
909 results << result;
910 }
911
912 return results.join( delimiter );
913}
914
915QVariant QgsAggregateCalculator::defaultValue( Qgis::Aggregate aggregate ) const
916{
917 // value to return when NO features are aggregated:
918 switch ( aggregate )
919 {
920 // sensible values:
924 return 0;
925
928 return ""; // zero length string - not null!
929
931 return QVariantList(); // empty list
932
933 // undefined - nothing makes sense here
950 return QVariant();
951 }
952 return QVariant();
953}
954
955QVariant QgsAggregateCalculator::calculateDateTimeAggregate( QgsFeatureIterator &fit, int attr, QgsExpression *expression,
957{
958 Q_ASSERT( expression || attr >= 0 );
959
961 QgsFeature f;
962
963 while ( fit.nextFeature( f ) )
964 {
965 if ( expression )
966 {
967 Q_ASSERT( context );
968 context->setFeature( f );
969 const QVariant v = expression->evaluate( context );
970 s.addValue( v );
971 }
972 else
973 {
974 s.addValue( f.attribute( attr ) );
975 }
976 }
977 s.finalize();
978 return s.statistic( stat );
979}
980
981QVariant QgsAggregateCalculator::calculateArrayAggregate( QgsFeatureIterator &fit, int attr, QgsExpression *expression,
982 QgsExpressionContext *context )
983{
984 Q_ASSERT( expression || attr >= 0 );
985
986 QgsFeature f;
987
988 QVariantList array;
989
990 while ( fit.nextFeature( f ) )
991 {
992 if ( expression )
993 {
994 Q_ASSERT( context );
995 context->setFeature( f );
996 const QVariant v = expression->evaluate( context );
997 array.append( v );
998 }
999 else
1000 {
1001 array.append( f.attribute( attr ) );
1002 }
1003 }
1004 return array;
1005}
1006
Statistic
Available generic statistics.
Definition qgis.h:4981
@ StDev
Standard deviation of values.
@ FirstQuartile
First quartile.
@ Mean
Mean of values.
@ Median
Median of values.
@ Max
Max of values.
@ Min
Min of values.
@ Range
Range of values (max - min)
@ Sum
Sum of values.
@ Minority
Minority of values.
@ CountMissing
Number of missing (null) values.
@ Majority
Majority of values.
@ Variety
Variety (count of distinct) values.
@ StDevSample
Sample standard deviation of values.
@ ThirdQuartile
Third quartile.
@ InterQuartileRange
Inter quartile range (IQR)
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
@ NoFlags
No flags are set.
StringStatistic
Available string statistics.
Definition qgis.h:5043
@ Max
Maximum string value.
@ Min
Minimum string value.
@ MaximumLength
Maximum length of string.
@ Minority
Minority of strings.
@ CountMissing
Number of missing (null) values.
@ Majority
Majority of strings.
@ CountDistinct
Number of distinct string values.
@ MinimumLength
Minimum length of string.
Aggregate
Available aggregates to calculate.
Definition qgis.h:4949
@ StDev
Standard deviation of values (numeric fields only)
@ StringMinimumLength
Minimum length of string (string fields only)
@ FirstQuartile
First quartile (numeric fields only)
@ Mean
Mean of values (numeric fields only)
@ Median
Median of values (numeric fields only)
@ Max
Max of values.
@ Min
Min of values.
@ StringMaximumLength
Maximum length of string (string fields only)
@ Range
Range of values (max - min) (numeric and datetime fields only)
@ StringConcatenateUnique
Concatenate unique values with a joining string (string fields only). Specify the delimiter using set...
@ Sum
Sum of values.
@ Minority
Minority of values.
@ CountMissing
Number of missing (null) values.
@ ArrayAggregate
Create an array of values.
@ Majority
Majority of values.
@ StDevSample
Sample standard deviation of values (numeric fields only)
@ ThirdQuartile
Third quartile (numeric fields only)
@ CountDistinct
Number of distinct values.
@ StringConcatenate
Concatenate values with a joining string (string fields only). Specify the delimiter using setDelimit...
@ GeometryCollect
Create a multipart geometry from aggregated geometries.
@ InterQuartileRange
Inter quartile range (IQR) (numeric fields only)
DateTimeStatistic
Available date/time statistics.
Definition qgis.h:5018
@ Max
Maximum (latest) datetime value.
@ Min
Minimum (earliest) datetime value.
@ Range
Interval between earliest and latest datetime value.
@ CountMissing
Number of missing (null) values.
@ CountDistinct
Number of distinct datetime values.
const QgsVectorLayer * layer() const
Returns the associated vector layer.
void setParameters(const AggregateParameters &parameters)
Sets all aggregate parameters from a parameter bundle.
void setFidsFilter(const QgsFeatureIds &fids)
Sets a filter to limit the features used during the aggregate calculation.
static QList< QgsAggregateCalculator::AggregateInfo > aggregates()
Structured information for available aggregates.
QVariant calculate(Qgis::Aggregate aggregate, const QString &fieldOrExpression, QgsExpressionContext *context=nullptr, bool *ok=nullptr, QgsFeedback *feedback=nullptr) const
Calculates the value of an aggregate.
QString delimiter() const
Returns the delimiter used for joining values with the StringConcatenate aggregate.
static QString displayName(Qgis::Aggregate aggregate)
Returns the friendly display name for a aggregate.
static Qgis::Aggregate stringToAggregate(const QString &string, bool *ok=nullptr)
Converts a string to a aggregate type.
QgsAggregateCalculator(const QgsVectorLayer *layer)
Constructor for QgsAggregateCalculator.
Calculator for summary statistics and aggregates for a list of datetimes.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly by the expression to check if evaluation sh...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the context.
static std::tuple< QMetaType::Type, int > determineResultType(const QString &expression, const QgsVectorLayer *layer, QgsFeatureRequest request=QgsFeatureRequest(), QgsExpressionContext context=QgsExpressionContext(), bool *foundFeatures=nullptr)
Returns a value type and user type for a given expression.
Class for parsing and evaluation of expressions (formerly called "search strings").
static int expressionToLayerFieldIndex(const QString &expression, const QgsVectorLayer *layer)
Attempts to resolve an expression to a field index from the given layer.
QVariant evaluate()
Evaluate the feature and return the result.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
void setFeedback(QgsFeedback *feedback)
Attach a feedback object that can be queried regularly by the iterator to check if it should be cance...
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
QgsFeatureRequest & setOrderBy(const OrderBy &orderBy)
Set a list of order by clauses.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:58
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition qgsfeedback.h:44
QMetaType::Type type
Definition qgsfield.h:60
QString name
Definition qgsfield.h:62
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
A geometry is the spatial representation of a feature.
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
Calculator for summary statistics for a list of doubles.
Calculator for summary statistics and aggregates for a list of strings.
Represents a vector layer which manages a vector based data sets.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsExpressionContext createExpressionContext() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QSet< QgsFeatureId > QgsFeatureIds
Structured information about the available aggregates.
A bundle of parameters controlling aggregate calculation.
QString filter
Optional filter for calculating aggregate over a subset of features, or an empty string to use all fe...
QString delimiter
Delimiter to use for joining values with the StringConcatenate aggregate.
QgsFeatureRequest::OrderBy orderBy
Optional order by clauses.