Aggregate Functions
You can group results with the group_by method. If you wish to further restrict the grouped result set, the having method can be applied.
info
Aggregation functions including max, min, sum, avg, count are available in ColumnTrait.
Sumβ
Sum a single columnβ
let sum_order_total: Decimal = order::Entity::find()
.select_only()
.column_as(order::Column::Total.sum(), "sum")
.into_tuple()
.one(db)
.await?
.unwrap();
Sum with group byβ
let (customer, total_spent): (String, Decimal) = customer::Entity::find()
.left_join(order::Entity)
.select_only()
.column(customer::Column::Name)
.column_as(order::Column::Total.sum(), "sum")
.group_by(customer::Column::Name)
.into_tuple()
.one(db)
.await?
.unwrap();
assert_eq!(customer, "Kate");
assert_eq!(total_spent, 25.into());
Group Byβ
The group_by method can take a column of the entity or a complex sea_query::SimpleExpr.
assert_eq!(
cake::Entity::find()
.select_only()
.column(cake::Column::Name)
.group_by(cake::Column::Name)
.build(DbBackend::Postgres)
.to_string(),
r#"SELECT "cake"."name" FROM "cake" GROUP BY "cake"."name""#
);
assert_eq!(
cake::Entity::find()
.select_only()
.column_as(cake::Column::Id.count(), "count")
.column_as(cake::Column::Id.sum(), "sum_of_id")
.group_by(cake::Column::Name)
.build(DbBackend::Postgres)
.to_string(),
r#"SELECT COUNT("cake"."id") AS "count", SUM("cake"."id") AS "sum_of_id" FROM "cake" GROUP BY "cake"."name""#
);
Using group by with aggregate functionsβ
#[derive(Debug, FromQueryResult)]
struct SelectResult {
name: String,
num_orders: i64,
total_spent: Decimal,
min_spent: Decimal,
max_spent: Decimal,
}
let select = customer::Entity::find()
.left_join(order::Entity)
.select_only()
.column(customer::Column::Name)
.column_as(order::Column::Total.count(), "num_orders")
.column_as(order::Column::Total.sum(), "total_spent")
.column_as(order::Column::Total.min(), "min_spent")
.column_as(order::Column::Total.max(), "max_spent")
.order_by_asc(customer::Column::Name)
.group_by(customer::Column::Name);
let result: Option<SelectResult> = select
.into_model()
.one(&ctx.db)
.await?;
Havingβ
The having method can take any conditional expressions introduced in the previous section.
assert_eq!(
cake::Entity::find()
.having(cake::Column::Id.eq(4))
.having(cake::Column::Id.eq(5))
.build(DbBackend::MySql)
.to_string(),
"SELECT `cake`.`id`, `cake`.`name` FROM `cake` HAVING `cake`.`id` = 4 AND `cake`.`id` = 5"
);
assert_eq!(
cake::Entity::find()
.select_only()
.column_as(cake::Column::Id.count(), "count")
.column_as(cake::Column::Id.sum(), "sum_of_id")
.group_by(cake::Column::Name)
.having(Expr::col("count").gt(6))
.build(DbBackend::MySql)
.to_string(),
"SELECT COUNT(`cake`.`id`) AS `count`, SUM(`cake`.`id`) AS `sum_of_id` FROM `cake` GROUP BY `cake`.`name` HAVING `count` > 6"
);