Gorm高级查询
前言
越高级,越复杂的查询,也同时意味着高耗,但是平时有一些数据少,但是业务复杂的场景,可以使用下。 这里主要说明的是 go 中使用 gorm 进务查询。gorm import 依赖 "database/sql" "fmt" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" 将查询结果放到一个 struct 中// 根据主键查询第一条记录 db.First(&user) //// SELECT * FROM users ORDER BY id LIMIT 1; // 随机获取一条记录 db.Take(&user) //// SELECT * FROM users LIMIT 1; // 根据主键查询最后一条记录 db.Last(&user) //// SELECT * FROM users ORDER BY id DESC LIMIT 1; // 查询所有的记录 db.Find(&users) //// SELECT * FROM users; // 查询指定的某条记录(仅当主键为整型时可用) db.First(&user, 10) //// SELECT * FROM users WHERE id = 10; 查询条件是map 或者 struct 查询
有时候代码是可需要映射到一个 map 结构, 不需要映射到一个 结构体中,可以写成如下:for update
在涉及并发的场景,往往需要加锁互斥,和 Java 类似, Go 中也有加行锁的方式,加 for update 即可。
一般写法如下: // 为查询 SQL 添加额外的 SQL 操作 db.Set("gorm:query_option", "FOR UPDATE").First(&user, 10) //// SELECT * FROM users WHERE id = 10 FOR UPDATE;
示例代码: err := db.Model(&XXX{}).Set("gorm:query_option", "FOR UPDATE").Where("XXX=?", XXX).First(&XXX).Error if err != nil { if err == gorm.ErrRecordNotFound { logs.Warn("xxx") return nil, nil } logs.Error("XXX") } Count 查询
有时候,我们需要进行简单的数据统计, 比如查询到结果有多少行, var count int64 db.Model(&User{}).Where("name = ?","jinzhu").Or("name = ?","jinzhu 2").Count(&count) // SELECT count(*) FROM users WHERE name = "jinzhu" OR name = "jinzhu 2" db.Model(&User{}).Where("name = ?","jinzhu").Count(&count) // SELECT count(*) FROM users WHERE name = "jinzhu"; (count) 分组计数
有时候也需要分组统计行数 // 分组计数 users :=[]User{ {Name:"name1"}, {Name:"name2"}, {Name:"name3"}, {Name:"name3"}, } DB.Model(&User{}).Group("name").Count(&count) count // => 3 去重统计// 去重计数 DB.Model(&User{}).Distinct("name").Count(&count) // SELECT COUNT(DISTINCT(`name`)) FROM `users` Group & Having
有时候我们会使用到数据统计的功能, 比如根据数据库字段 batch_no 进行分组,然后统计总金额,总笔数。
分组查询统计一般的写法如下: db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Having("sum(amount) > ?", 100).Scan(&results)
代码示例: type Sum struct { BatchNo string `gorm:"column:batch_no" json:"batch_no"` TotalCounts int64 `gorm:"column:total_counts" json:"total_counts"` TotalAmounts int64 `gorm:"column:total_amounts" json:"total_amounts"` } var result []*Sum db := db.Model(&Voucher{}).Select("batch_no, count(1) as totalCounts, sum(amount) as totalAmounts") status := []string{10,20,40} db = db.Where("no >= ?", startVoucherNo) db = db.Where("no <= ?", endVoucherNo) db = db.Where("batch_no IN ?", batchNos) db = db.Where("status IN ?", status) if shardingKey >= 0 { db = db.Where("sharding_key = ", shardingKey) } db = db.Group("batch_no") err := db.Scan(&result).Error if err != nil { if err == gorm.ErrRecordNotFound { logs.CtxWarn("xxx") return nil, nil } logs.CtxError(ctx, "xxx", err) } Join 查询
一般来说,很少使用关联查询,但是如果要使用关联查询,可以如下: db.Table("users").Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Scan(&results) // 多连接及参数 db.Joins("JOIN emails ON emails.user_id = users.id AND emails.email = ?", "jinzhu@example.org").Joins("JOIN credit_cards ON credit_cards.user_id = users.id").Where("credit_cards.number = ?", "411111111111").Find(&user) 查询指定函数
Scopes 允许你指定常用的查询,可以在调用方法时引用这些查询, 也就是说,可以在查询中使用函数。
举个例子: func AmountGreaterThan1000(db *gorm.DB)*gorm.DB { return db.Where("amount > ?",1000) } func PaidWithCreditCard(db *gorm.DB)*gorm.DB { return db.Where("pay_mode_sign = ?","C") } func PaidWithCod(db *gorm.DB)*gorm.DB { return db.Where("pay_mode_sign = ?","C") } db.Scopes(AmountGreaterThan1000,PaidWithCreditCard).Find(&orders) // 查找所有金额大于 1000 的信用卡订单 db.Scopes(AmountGreaterThan1000,PaidWithCod).Find(&orders) // 查找所有金额大于 1000 的货到付款订单 欢迎关注:程序员财富自由之路
在这里插入图片描述 参考资料https://www.cnblogs.com/zisefeizhu/p/12788060.html https://gorm.io/zh_CN/docs/advanced_query.html https://www.bookstack.cn/read/gorm-2.0/docs-advanced_query.md#4abzu1