聚合、分组和汇总
Prisma Dart 客户端允许您计算记录数、聚合数字字段以及选择不同的字段值。
聚合
Prisma Dart 客户端允许您对模型的**数字**字段(例如Int
和Float
)进行aggregate
操作。以下查询返回所有用户的平均年龄
dart
final aggregate1 = await prisma.user.aggregate(
select: AggregateUserSelect(
$avg: PrismaUnion.$2(
AggregateUserAvgArgs(
select: UserAvgAggregateOutputTypeSelect(age: true),
),
),
),
);
print("Average age: ${aggregate1.$avg?.age}");
您可以将聚合与过滤和排序结合使用。例如,以下查询返回用户的平均年龄
- 按
age
升序排序 - 其中
email
包含hello
- 限制为前10个用户
dart
final aggregate2 = await prisma.user.aggregate(
select: AggregateUserSelect(
$avg: PrismaUnion.$2(
AggregateUserAvgArgs(
select: UserAvgAggregateOutputTypeSelect(age: true),
),
),
),
where: UserWhereInput(
email: PrismaUnion.$1(
StringFilter(contains: PrismaUnion.$1('hello')),
),
),
take: 10,
);
print("Average age: ${aggregate2.$avg?.age}");
聚合值可以为 null
对**可空字段**的聚合可以返回num
或null
。这排除了$count
,如果未找到任何记录,它始终返回0。
考虑以下查询,其中age
在模式中是可空的
dart
await prisma.user.aggregate(
select: AggregateUserSelect(
$avg: PrismaUnion.$2(
AggregateUserAvgArgs(
select: UserAvgAggregateOutputTypeSelect(age: true),
),
),
$count: PrismaUnion.$2(
AggregateUserCountArgs(
select: UserCountAggregateOutputTypeSelect(age: true),
),
),
),
);
在以下任何一种情况下,查询都会返回{ _avg: { age: null } }
- 没有用户
- 每个用户的
age
字段的值均为null
这使您能够区分真正的聚合值(可能是零)和无数据。
分组依据
Prisma Datr 客户端groupBy
允许您按一个或多个字段值(例如country
或country
和city
)**对记录进行分组**,并在每个组中**执行聚合**操作,例如查找居住在特定城市的人的平均年龄。
以下示例按country
字段对所有用户进行分组,并返回每个国家/地区的个人资料查看总数
dart
await prisma.user.groupBy(
by: PrismaUnion.$1([
UserScalar.country,
]),
select: UserGroupByOutputTypeSelect(
country: true,
$sum: PrismaUnion.$2(
UserGroupByOutputTypeSumArgs(
select: UserSumAggregateOutputTypeSelect(
profileViews: true,
),
),
),
),
);
如果您在by选项中只有一个元素,则可以使用以下简写语法来表达您的查询
dart
await prisma.user.groupBy(
by: PrismaUnion.$2(UserScalar.country),
);
groupBy
和过滤
groupBy
支持两个级别的过滤:where
和having
。
使用where
过滤记录
使用where
在**分组前**过滤所有记录。以下示例按国家/地区对用户进行分组并对个人资料查看次数求和,但仅包括电子邮件地址包含test
的用户
dart
await prisma.user.groupBy(
by: PrismaUnion.$1([
UserScalar.country,
]),
select: UserGroupByOutputTypeSelect(
country: true,
$sum: PrismaUnion.$2(
UserGroupByOutputTypeSumArgs(
select: UserSumAggregateOutputTypeSelect(
profileViews: true,
),
),
),
),
where: UserWhereInput(
email: PrismaUnion.$1(
StringFilter(contains: PrismaUnion.$1('test')),
),
),
);
使用having
过滤组
使用having
按聚合值(例如字段的总和或平均值)过滤整个组,而不是单个记录——例如,仅返回平均profileViews大于100的组
dart
await prisma.user.groupBy(
by: PrismaUnion.$1([
UserScalar.country,
]),
select: UserGroupByOutputTypeSelect(
country: true,
$sum: PrismaUnion.$2(
UserGroupByOutputTypeSumArgs(
select: UserSumAggregateOutputTypeSelect(
profileViews: true,
),
),
),
),
having: UserScalarWhereWithAggregatesInput(
profileViews: PrismaUnion.$1(
IntWithAggregatesFilter(
$avg: NestedFloatFilter(
gt: PrismaUnion.$1(100),
),
),
),
),
);
groupBy
和排序
当您将groupBy
和orderBy
结合使用时,适用以下约束条件
- 您可以对
by
中存在的字段进行orderBy
- 您可以对聚合进行
orderBy
- 如果您将
skip
和/或take
与groupBy
一起使用,则必须在查询中也包含orderBy
按聚合组排序
以下示例按每个city
组中的用户数量对每个city
组进行排序(最大的组排在最前面)
dart
await prisma.user.groupBy(
by: PrismaUnion.$1([UserScalar.city]),
select: UserGroupByOutputTypeSelect(
city: true,
$count: PrismaUnion.$2(
UserGroupByOutputTypeCountArgs(
select: UserCountAggregateOutputTypeSelect(
city: true,
),
),
),
),
orderBy: PrismaUnion.$2(
UserOrderByWithAggregationInput(
$count: UserCountOrderByAggregateInput(
city: SortOrder.desc,
),
),
),
);
按字段排序
以下查询按国家/地区对组进行排序,跳过前两个组,并返回第3个和第4个组
dart
await prisma.user.groupBy(
by: PrismaUnion.$1([UserScalar.country]),
select: UserGroupByOutputTypeSelect(
country: true,
$sum: PrismaUnion.$2(
UserGroupByOutputTypeSumArgs(
select: UserSumAggregateOutputTypeSelect(
profileViews: true,
),
),
),
),
orderBy: PrismaUnion.$2(
UserOrderByWithAggregationInput(
$count: UserCountOrderByAggregateInput(
country: SortOrder.desc,
),
),
),
take: 2,
skip: 2,
);