diff --git a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/AggregationSortByForm.vue b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/AggregationSortByForm.vue
new file mode 100644
index 000000000..9434b1a9d
--- /dev/null
+++ b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/AggregationSortByForm.vue
@@ -0,0 +1,123 @@
+<template>
+  <FormSection
+    :title="$t('aggregationSortByForm.sortByFieldLabel')"
+    class="margin-bottom-2"
+  >
+    <Dropdown
+      :value="sortByField"
+      :show-search="true"
+      fixed-items
+      class="margin-bottom-1"
+      :error="v$.sortByField?.$error || false"
+      @change="sortByFieldChangedByUser($event)"
+    >
+      <DropdownItem
+        :name="$t('aggregationSortByForm.none')"
+        :value="null"
+      ></DropdownItem>
+      <DropdownItem
+        v-for="field in allowedSortFields"
+        :key="field.id"
+        :name="field.name"
+        :value="field.id"
+        :icon="fieldIconClass(field)"
+      >
+      </DropdownItem>
+    </Dropdown>
+    <SegmentControl
+      :active-index="orderByIndex"
+      :segments="orderByOptions"
+      :initial-active-index="orderByIndex"
+      @update:activeIndex="orderByChangedByUser"
+    ></SegmentControl>
+  </FormSection>
+</template>
+
+<script>
+import { useVuelidate } from '@vuelidate/core'
+
+const includesIfSet = (array) => (value) => {
+  if (value === null || value === undefined) {
+    return true
+  }
+  return array.includes(value)
+}
+
+export default {
+  name: 'AggregationGroupByForm',
+  props: {
+    allowedSortFields: {
+      type: Array,
+      required: true,
+    },
+    aggregationSorts: {
+      type: Array,
+      required: true,
+    },
+  },
+  setup() {
+    return { v$: useVuelidate({ $lazy: true }) }
+  },
+  data() {
+    return {
+      sortByField: null,
+      orderByIndex: 0,
+    }
+  },
+  computed: {
+    orderByOptions() {
+      return [
+        { label: this.$t('aggregationSortByForm.ascending'), value: 'ASC' },
+        { label: this.$t('aggregationSortByForm.descending'), value: 'DESC' },
+      ]
+    },
+  },
+  watch: {
+    aggregationSorts: {
+      handler(aggregationSorts) {
+        if (aggregationSorts.length !== 0) {
+          this.sortByField = aggregationSorts[0].field
+          this.orderByIndex = this.orderByOptions.findIndex(
+            (item) => item.value === aggregationSorts[0].order_by
+          )
+        }
+      },
+      immediate: true,
+    },
+  },
+  mounted() {
+    this.v$.$validate(true)
+  },
+  validations() {
+    const self = this
+    return {
+      sortByField: {
+        isValidSortFieldId: (value) => {
+          const ids = self.allowedSortFields.map((item) => item.id)
+          return includesIfSet(ids)(value)
+        },
+      },
+    }
+  },
+  methods: {
+    sortByFieldChangedByUser(value) {
+      this.sortByField = value
+      this.$emit('value-changed', {
+        field: value,
+        order_by: this.orderByOptions[this.orderByIndex].value,
+      })
+    },
+    orderByChangedByUser(index) {
+      this.orderByIndex = index
+      this.$emit('value-changed', {
+        field: this.sortByField,
+        order_by: this.orderByOptions[index].value,
+      })
+    },
+    fieldIconClass(field) {
+      const fieldType = this.$registry.get('field', field.type)
+      return fieldType.iconClass
+    },
+  },
+}
+</script>
diff --git a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/GroupedAggregateRowsDataSourceForm.vue b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/GroupedAggregateRowsDataSourceForm.vue
index 3567d9f09..47eb4356b 100644
--- a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/GroupedAggregateRowsDataSourceForm.vue
+++ b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/GroupedAggregateRowsDataSourceForm.vue
@@ -99,6 +99,13 @@
       @value-changed="onGroupByUpdated($event)"
     >
     </AggregationGroupByForm>
+    <AggregationSortByForm
+      v-if="values.table_id && !fieldHasErrors('table_id')"
+      :aggregation-sorts="values.sortings"
+      :allowed-sort-fields="allowedSortFields"
+      @value-changed="onSortByUpdated($event)"
+    >
+    </AggregationSortByForm>
   </form>
 </template>
 
@@ -108,6 +115,7 @@ import form from '@baserow/modules/core/mixins/form'
 import { required } from '@vuelidate/validators'
 import AggregationSeriesForm from '@baserow_enterprise/dashboard/components/data_source/AggregationSeriesForm'
 import AggregationGroupByForm from '@baserow_enterprise/dashboard/components/data_source/AggregationGroupByForm'
+import AggregationSortByForm from '@baserow_enterprise/dashboard/components/data_source/AggregationSortByForm'
 
 const includesIfSet = (array) => (value) => {
   if (value === null || value === undefined) {
@@ -118,7 +126,11 @@ const includesIfSet = (array) => (value) => {
 
 export default {
   name: 'GroupedAggregateRowsDataSourceForm',
-  components: { AggregationSeriesForm, AggregationGroupByForm },
+  components: {
+    AggregationSeriesForm,
+    AggregationGroupByForm,
+    AggregationSortByForm,
+  },
   mixins: [form],
   props: {
     dashboard: {
@@ -149,12 +161,14 @@ export default {
         'view_id',
         'aggregation_series',
         'aggregation_group_bys',
+        'sortings',
       ],
       values: {
         table_id: null,
         view_id: null,
         aggregation_series: [],
         aggregation_group_bys: [],
+        sortings: [],
       },
       tableLoading: false,
       databaseSelectedId: null,
@@ -200,6 +214,19 @@ export default {
     tableViewIds() {
       return this.tableViews.map((view) => view.id)
     },
+    allowedSortFields() {
+      console.log('updating allowed sort fields')
+      const seriesFieldIds = this.values.aggregation_series.map(
+        (item) => item.field_id
+      )
+      const groupByFieldIds = this.values.aggregation_group_bys.map(
+        (item) => item.field_id
+      )
+      const allowedFieldIds = seriesFieldIds.concat(groupByFieldIds)
+      return this.tableFields.filter((item) => {
+        return allowedFieldIds.includes(item.id)
+      })
+    },
   },
   watch: {
     dataSource: {
@@ -291,6 +318,12 @@ export default {
         aggregation_group_bys: aggregationGroupBys,
       })
     },
+    onSortByUpdated(sortBy) {
+      const aggregationSorts = sortBy.field !== null ? [sortBy] : []
+      this.$emit('values-changed', {
+        sortings: aggregationSorts,
+      })
+    },
   },
 }
 </script>
diff --git a/enterprise/web-frontend/modules/baserow_enterprise/locales/en.json b/enterprise/web-frontend/modules/baserow_enterprise/locales/en.json
index b65c86e7a..8705dadab 100644
--- a/enterprise/web-frontend/modules/baserow_enterprise/locales/en.json
+++ b/enterprise/web-frontend/modules/baserow_enterprise/locales/en.json
@@ -460,5 +460,11 @@
     "groupByFieldLabel": "Group by",
     "groupByNone": "None",
     "groupByRowId": "Row Id"
+  },
+  "aggregationSortByForm": {
+    "sortByFieldLabel": "Sort by",
+    "none": "None",
+    "ascending": "Ascending",
+    "descending": "Descending"
   }
 }