使用GORM的Joins关联查询时如何将LEFT JOIN替换为INNER JOIN
GORM中通过关联名称实现INNER JOIN查询2022年出生用户的方法
首先是你定义的结构体:
type User struct { ID uuid.UUID `gorm:"type:uuid"` BirthDate *BirthDate `gorm:"<-"` BirthDateID uuid.UUID } type BirthDate struct { ID uuid.UUID `gorm:"type:uuid"` Year int Month int Day int }
你需要查询2022年出生的用户,使用Joins("BirthDate", query)时默认生成LEFT JOIN,导致结果不符合预期。以下两种方法可以实现用关联名称的方式达成INNER JOIN的效果:
方法一:显式指定INNER JOIN类型
通过GORM的clause.Join结构体,直接指定连接类型为INNER JOIN,同时关联查询条件:
var result []*User // 构造BirthDate的查询条件 birthDateQuery := DB.Model(&BirthDate{}).Select("id").Where("year = ?", 2022) DB.Debug().Joins( clause.Join{ Table: clause.Table{Name: "birth_dates"}, // 关联表名 Alias: "BirthDate", // 关联别名,和结构体中字段名一致 Type: clause.INNERJoin, // 指定INNER JOIN类型 On: clause.Where{ Exprs: []clause.Expression{ // 关联外键条件 clause.Eq{Column: clause.Column{Table: "users", Name: "birth_date_id"}, Value: clause.Column{Table: "BirthDate", Name: "id"}}, // 带入BirthDate的查询条件 clause.Where{Exprs: birthDateQuery.Statement.Clauses["WHERE"].Exprs}, }, }, }, ).Preload(clause.Associations).Find(&result)
方法二:过滤LEFT JOIN中的空关联记录
这种方法更简洁,利用Where过滤掉关联字段为空的记录,等价于INNER JOIN的效果:
var result []*User birthDateExample := BirthDate{Year:2022} DB.Debug().Joins("BirthDate", DB.Select("id").Where(birthDateExample)). Where("BirthDate.id IS NOT NULL"). // 过滤无匹配关联的用户 Preload(clause.Associations).Find(&result)
这两种方法都不需要手写完整的JOIN语句,符合你想要的通过关联名称实现查询的需求。
内容的提问来源于stack exchange,提问作者Manuelarte
相关产品推荐
相关产品推荐

