You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 03:05:19