V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
imherer
V2EX  ›  Go 编程语言

gorm 联合查询的时候如何只查询指定字段?

  •  
  •   imherer · 2019-08-19 11:11:49 +08:00 · 8561 次点击
    这是一个创建于 1960 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有如下三个 struct

    type Article struct {
    	gorm.Model
    	CategoryID int            `json:"-" gorm:"not null"`
    	Category   Category       `json:"category" gorm:"ForeignKey:CategoryID;`
    	Title      string         `json:"title" gorm:"not null;type:varchar(100);"`
    	AuthorID   int            `json:"-"`
    	Author     Author         `gorm:"ForeignKey:AuthorID"`
    	Content    string         `json:"content" gorm:"not null;type:text"`
    }
    type Category struct {
    	ID   uint   `json:"id" gorm:"primary_key;AUTO_INCREMENT"`
    	Name string `json:"name" gorm:"type:varchar(100)"`
    	Max  int    `json:"max"`
    }
    type Author struct {
    	gorm.Model
    	Name string `json:"name"`
    }
    
    

    想实现如下的 SQL 应该如何写呢?

    SELECT a.id,a.title,b.name as category,c.name as author FROM article a, category b, author c WHERE a.category_id=b.id AND a. author_id = c.id AND a.category_id =1
    
    // 这样是查询出了三张表的所有字段,Select 好像只支持当前表的字段
    // list := []Article{}
    // mysql.Preload("Author").Preload("Category").Find(&list, "category_id=?", 1)
    
    
    11 条回复    2019-08-19 19:17:20 +08:00
    janxin
        1
    janxin  
       2019-08-19 11:28:52 +08:00
    gorm 的 perload 不是联合查询吧

    gorm.io/docs/sql_builder.html#Run-Raw-SQL 试试这个?
    imherer
        2
    imherer  
    OP
       2019-08-19 11:35:03 +08:00
    @janxin Preload 是联合查询的

    我现在也的解决方案也是 raw
    janxin
        3
    janxin  
       2019-08-19 11:54:33 +08:00
    @imherer gorm.io/docs/preload.html#Preload 文档不是这么说的吧
    xiaoyiyu
        4
    xiaoyiyu  
       2019-08-19 14:18:06 +08:00
    keepeye
        5
    keepeye  
       2019-08-19 14:34:52 +08:00
    Custom Preloading SQL
    You could custom preloading SQL by passing in func(db *gorm.DB) *gorm.DB, for example:

    db.Preload("Orders", func(db *gorm.DB) *gorm.DB {
    return db.Order("orders.amount DESC")
    }).Find(&users)
    //// SELECT * FROM users;
    //// SELECT * FROM orders WHERE user_id IN (1,2,3,4) order by orders.amount DESC;
    ylsc633
        6
    ylsc633  
       2019-08-19 15:08:14 +08:00
    不知道你们用 gorm 有没有发现 gorm 关联查询有个问题!

    比如 user role permission 三个表, user 与 role 是多对多的关系, role 与 permission 是多对多的关系!

    如果我想查 模糊查询 user 的 name like test, 然后限定 角色 role = default 的

    在 gorm 里用 Preload 会出现两条 sql, 一条是 select * from user where username like %test%

    第二条是 select * from role inner join user_role on user_role.role_id = role.id where role.name = default

    然后 gorm 会把第二条的数据关联回第一条的结果上!

    可是这样跟要求是不一致的!

    不知道你们有没有发现这个!

    所以真的有这种需求的时候,建议 手写 sql 或者 join
    dongya
        7
    dongya  
       2019-08-19 16:19:27 +08:00
    直接写 sql 呀
    shingle
        8
    shingle  
       2019-08-19 16:32:38 +08:00
    db.Table("article a").Select("a.id,a.title,b.name as category,c.name as author").Joins("left join category b on a.category_id = b.id").Joins("left join author c on a.author_id = c.id AND a.category_id =1").Scan()
    imherer
        9
    imherer  
    OP
       2019-08-19 17:08:08 +08:00
    @ylsc633 是的。简单的用 gorm,复杂的就直接手写 sql 了
    ylsc633
        10
    ylsc633  
       2019-08-19 17:45:03 +08:00
    @imherer 手写 sql 有个不好的就是 得写死 表名!

    万一改了表名(改表名,换了新表,添加修改前缀等)就得哭!

    除非调用 tablename 方法,不过这样就得拼凑字符串了......
    imherer
        11
    imherer  
    OP
       2019-08-19 19:17:20 +08:00
    @ylsc633 对的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1009 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 22:28 · PVG 06:28 · LAX 14:28 · JFK 17:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.