04-高级查询

1. 用Struct或Map接收数据

1.1 Find到Struct

定义一个小的结构体来接收表中的查询结果

db.Model(User{}).Find(&UserModels)
  • 完整示例
    已有数据表
mysql> select * from users;
+----+----------+------+--------------------+
| id | name | age | email |
+----+----------+------+--------------------+
| 1 | LiuBei | 28 | liubei@xishu.com |
| 2 | GuanYu | 22 | guanyu@xishu.com |
| 3 | ZhangFei | 20 | zhangfei@xishu.com |
+----+----------+------+--------------------+
3 rows in set (0.00 sec)

代码

package main
import (
"database/sql"
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"time"
)
type User struct {
ID int64
Age int64
Name string
Email string
}
type userModel struct {
ID int64
Name string
}
func main() {
db,sqlDB,_ := connect()
defer sqlDB.Close()
var UserModels []userModel
db.Model(User{}).Find(&UserModels)
fmt.Println(UserModels)
}
func connect() (db *gorm.DB,sqlDB *sql.DB,err error) {
dsn := "root:40010355@tcp(127.0.0.1:3306)/crow?charset=utf8&parseTime=True&loc=Local"
db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
sqlDB,_ = db.DB()
if err != nil {
fmt.Printf(err.Error())
defer sqlDB.Close()
}else {
fmt.Printf("OK\n")
sqlDB.SetMaxIdleConns(10)
sqlDB.SetMaxOpenConns(100)
sqlDB.SetConnMaxLifetime(time.Hour)
}
return
}

结果输出

OK
[{1 LiuBei} {2 GuanYu} {3 ZhangFei}]

1.2 Find到Map

定义一个Map来接收数据

func main() {
db,sqlDB,_ := connect()
defer sqlDB.Close()
var users map[string]interface{}
db.Table("users").Find(&users)
fmt.Println(users)
}

2. 子查询

db.Where("age > (?)", db.Table("users").Select("AVG(age)")).Find(&users)
// SELECT * FROM "users" WHERE age > (SELECT AVG(age) FROM "users");
  • 示例
func main() {
db,sqlDB,_ := connect()
defer sqlDB.Close()
var users []User
db.Where("age > (?)", db.Table("users").Select("AVG(age)")).Find(&users)
fmt.Println(users)
}
  • 查询结果
OK
[{1 28 LiuBei liubei@xishu.com}]

3. Group/Having

3.1 Group

求和、平均值等情况的分组

db.Table("users").Select("AVG(age) as avg_age","company").Group("company").Find(&users)

完整示例

求下表中各公司的平均年龄

  • 数据表
mysql> select * from users;
+----+----------+------+--------------------+---------+
| id | name | age | email | company |
+----+----------+------+--------------------+---------+
| 1 | LiuBei | 28 | liubei@xishu.com | shu |
| 2 | GuanYu | 22 | guanyu@xishu.com | shu |
| 3 | ZhangFei | 20 | zhangfei@xishu.com | shu |
| 4 | SunQuan | 22 | sunquan@dongwu.com | wu |
| 5 | ZhouYu | 15 | zhouyu@dongwu.com | wu |
+----+----------+------+--------------------+---------+
5 rows in set (0.00 sec)
  • 代码
package main
import (
"database/sql"
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"time"
)
type User struct {
ID int64
Age int64
Name string
Email string
Company string
}
type groupBy struct {
AvgAge float64
Company string
}
func main() {
db,sqlDB,_ := connect()
defer sqlDB.Close()
var users []groupBy
db.Table("users").Select("AVG(age) as avg_age","company").Group("company").Find(&users)
fmt.Println(users)
}
func connect() (db *gorm.DB,sqlDB *sql.DB,err error) {
dsn := "root:40010355@tcp(127.0.0.1:3306)/crow?charset=utf8&parseTime=True&loc=Local"
db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
sqlDB,_ = db.DB()
if err != nil {
fmt.Printf(err.Error())
defer sqlDB.Close()
}else {
fmt.Printf("OK\n")
sqlDB.SetMaxIdleConns(10)
sqlDB.SetMaxOpenConns(100)
sqlDB.SetConnMaxLifetime(time.Hour)
}
return
}
  • 输出结果
OK
[{23.3333 shu} {18.5 wu}]

3.2 Having

对Group的结果进行过滤。上例中得到的结果,用Having得到平均值大于20的结果。

db.Table("users").Select("AVG(age) as avg_age","company").Group("company").Having("avg_age > ?",20).Find(&users)

4. 变量

4.1 使用sql.Named定义

db.Where("age > @age AND company = @company", sql.Named("company", "shu"),sql.Named("age", 20)).Find(&users)

4.2 使用map定义变量

db.Where("age > @age AND company = @company",map[string]interface{}{"company": "shu","age":20}).First(&users)
  • 示例
func main() {
db,sqlDB,_ := connect()
defer sqlDB.Close()
var users []User
checkUser := map[string]interface{}{
"company":"shu",
"age":20,
}
db.Where("age > @age AND company = @company",checkUser).First(&users)
fmt.Println(users)
}

5. 用Rows() 迭代

  • 使用
    用Rows() 记录数据 ----> rows.Next()逐行读出-----> 用ScanRows赋值给结构体

  • 示例

func main() {
db,sqlDB,_ := connect()
defer sqlDB.Close()
rows, _ := db.Model(&User{}).Where("company = ?", "shu").Rows()
defer rows.Close()
for rows.Next() {
var user User
// ScanRows 方法用于将一行记录扫描至结构体
db.ScanRows(rows, &user)
fmt.Println(user)
}
}

6. 查钩子

写一个查询钩子,当查询结果字段Company为空时,替换为"群"

func (u *User) AfterFind(tx *gorm.DB) (err error) {
if u.Company == "" {
u.Company = "qun"
}
return
}

7. Pluck(单列查询)

  • 作用
    查询单列数据,并用一个切片接收
  • 样例
db.Model(&User{}).Pluck("name", &names)
  • 代码
func main() {
db,sqlDB,_ := connect()
defer sqlDB.Close()
var names []string
db.Model(&User{}).Pluck("name", &names)
fmt.Println(names)
}
  • 输出
[LiuBei GuanYu ZhangFei YuJi ZhaoYun]

8. Scopes(调用查询函数)

8.1 使用

  • 作用
    我们可以使用Scopes调用事先创建好的函数。
  • 样例
db.Scopes(函数1,函数2).Find(&users)

8.2 示例

  • 创建函数

创建一个函数用来查询年龄大约20岁的用户数据

func ageGT20db (db *gorm.DB) *gorm.DB {
return db.Where("age > ?",20)
}
  • 调用函数
func main() {
db,sqlDB,_ := connect()
defer sqlDB.Close()
var users []User
db.Scopes(ageGT20db).Find(&users)
fmt.Println(users)
}

9. Count

  • 作用
    统计查到了多少条数据

  • 代码

func main() {
db,sqlDB,_ := connect()
defer sqlDB.Close()
var count int64
var users []User
db.Find(&users).Count(&count)
fmt.Println(count)
}

posted on   运维开发玄德公  阅读(17)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示