OOro

选择与聚合

Select、Raw 表达式、GroupBy、Having、Count、Sum、Avg、Min、Max 和关系聚合。

Select 只保留一个入口:字段名、聚合表达式和 oro.Raw(...) 都放在同一个方法里。

字段名规则按查询入口区分,SelectWhereGroupByHavingOrderBy 都遵循同一套规则:

入口 字段名写法
db.Use[T]() Go 字段名,如 CreatedAtPrice
db.Table(name) 数据库列名,如 created_atprice
db.Raw(sql) / oro.Raw(sql) 手写 SQL,自己决定

oro.Countoro.Sumoro.Avgoro.Minoro.Max 在模型查询里也遵循 Go 字段名规则。

选择字段

products, err := db.Use[Product]().Select("ID", "Code", "Price").Get(ctx)

裸表查询使用数据库列名:

rows, err := db.Table("products").Select("id", "code", "price").Get(ctx)

Raw 表达式

rows, err := db.Table("orders").
    Select("status", oro.Raw("sum(total) as revenue")).
    GroupBy("status").
    Get(ctx)

Raw 选择表达式统一写成 Select(oro.Raw(...)),不再额外拆一个并行 API。

聚合表达式

rows, err := db.Use[Order]().
    Select("Status", oro.Count("*").As("total"), oro.Sum("Total").As("revenue")).
    GroupBy("Status").
    Get(ctx)

可用聚合表达式:

表达式 SQL 语义
oro.Count(field) count(field)
oro.Sum(field) sum(field)
oro.Avg(field) avg(field)
oro.Min(field) min(field)
oro.Max(field) max(field)
.As(alias) 设置结果别名

模型查询中 oro.Sum("Total") 使用 Go 字段名;裸表查询中 oro.Sum("total") 使用数据库列名。oro.Count("*") 是特殊写法,表示 count(*)

GroupBy 和 Having

rows, err := db.Use[Order]().
    Select("Status", oro.Count("*").As("total")).
    GroupBy("Status").
    HavingRaw("count(*) > ?", 10).
    Get(ctx)

Having 的参数规则和 Where 类似,但作用在分组结果上。结构化 Having 的字段名仍遵循入口规则;按聚合表达式或聚合别名过滤时用 HavingRaw 更明确:

Having("Status", "paid")        // 模型查询:Go 字段名
Having("status", "paid")        // 裸表查询:数据库列名
HavingRaw("count(*) > ?", 10)    // 聚合表达式
HavingColumn("paid_total", ">", "refunded_total")

子查询场景使用 HavingIn / HavingExists

vipStatuses := oro.Query(
    db.Table("vip_statuses").Select("status"),
)

rows, err := db.Table("orders").
    Select("status", oro.Count("*").As("total")).
    GroupBy("status").
    HavingIn("status", vipStatuses).
    Get(ctx)

终结聚合方法

count, err := db.Use[Order]().Where("Status", "paid").Count(ctx)
exists, err := db.Use[Order]().Where("Status", "paid").Exists(ctx)
sum, err := db.Use[Order]().Sum(ctx, "Total")
avg, err := db.Use[Order]().Avg(ctx, "Total")
min, err := db.Use[Order]().Min[uint](ctx, "Total")
max, err := db.Use[Order]().Max[uint](ctx, "Total")
方法 返回
Count int64
Exists bool
Sum / Avg oro.Decimal
Min[T] / Max[T] oro.Null[T]

MinMax 使用 Null[T],因为空集合没有最小/最大值。

关系聚合

articles, err := db.Use[Article]().
    WithCount(Article{}.Comments()).
    WithExists(Article{}.Cover()).
    WithSum(Article{}.Comments(), "Score", func(q *oro.RelationQuery) {
        q.Where("Status", "approved")
    }).
    Get(ctx)

模型中用虚拟字段接收结果:

type Article struct {
    oro.Model
    Title         string
    CommentsCount int64
}

func (Article) Define(s *oro.SchemaBuilder) {
    s.Field("CommentsCount").Virtual()
}
编辑此页