首页 > 其他分享 >11-gorm-V2-04-高级查询

11-gorm-V2-04-高级查询

时间:2023-06-28 13:56:55浏览次数:48  
标签:11 gorm users 04 age db sqlDB V2 company

@

目录

1. 用Struct或Map接收数据

1.1 Find到Struct

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

db.Model(User{}).Find(&UserModels)
  • 完整示例
    已有数据表
mysql> select * from users;
+----+----------+------+--------------------+
| id | name     | age  | email              |
+----+----------+------+--------------------+
|  1 | LiuBei   |   28 | [email protected]   |
|  2 | GuanYu   |   22 | [email protected]   |
|  3 | ZhangFei |   20 | [email protected] |
+----+----------+------+--------------------+
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 [email protected]}]

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 | [email protected]   | shu     |
|  2 | GuanYu   |   22 | [email protected]   | shu     |
|  3 | ZhangFei |   20 | [email protected] | shu     |
|  4 | SunQuan  |   22 | [email protected] | wu      |
|  5 | ZhouYu   |   15 | [email protected]  | 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)
}

标签:11,gorm,users,04,age,db,sqlDB,V2,company
From: https://www.cnblogs.com/crow1840/p/17511199.html

相关文章

  • 11-gormV2-07-删除
    1.按主键删除1.1使用说明如果指定的不是主键,则会触发批量删除,但是没有Where的批量删除被gorm禁止。样例db.Delete(&User{ID:2})或写做db.Delete(&User{ID:2},2)1.2完整示例删除id=2的一行packagemainimport( "database/sql" "fmt" "gorm.io/driver/m......
  • 二、Windows11平台下Visual Studio 2022配置32位汇编环境
    1.下载VisualStudio20222.安装选择工作负载3.创建新项目3.1选择空项目模板3.2填写项目名称和解决方案项目名称:实际项目名称解决方案名称:一个解决方案下可以管理多个项目,并且可以选择一个项目为启动项目,当点击运行与调试后,就会启动被选择为启动项目的项目3.3实......
  • FX110网WeTrade众汇平台:交易者应该使用 MT4 还是 MT5?
    比较MT4和MT5是许多外汇交易者感兴趣的话题。这两款软件均由MetaQuotes开发,广泛应用于外汇交易行业。尽管两者都提供交易工具和功能,但它们之间存在重要差异。在本文中,FX110网上的交易商WeTrade众汇平台将探讨和比较MT4和MT5,以帮助您选择适合您的交易需求和目标的软件。MT4和M......
  • 解决:远程连接mysql:报异常,1044 - Access denied for user ‘root‘@‘%‘ to database
    Navicat报错:使用Navicat远程连接,Docker中的mysql5.6时报异常,:1044-Accessdeniedforuser'root'@'%'todatabase'xxx'问题原因:(1)根本原因:远程连接用户权限不足!(2)直接原因:应该是创建远程连接用户‘root@%’时,没有添加访问数据库的权限。解决办法:#这里为刚才创建的root@......
  • 编程初学者入门11_井字棋游戏、进制转换、订闹钟(时间换算)
    一、井字棋游戏题目描述KiKi和BoBo玩“井”字棋。也就是在九宫格中,只要任意行、列,或者任意对角线上面出现三个连续相同的棋子,就能获胜。请根据棋盘状态,判断当前输赢。输入描述:三行三列的字符元素,代表棋盘状态,字符元素用空格分开,代表当前棋盘,其中元素为K代表KiKi玩家的棋子,为O表......
  • PTA实验实验7~11的总结及分析
    1.前言自上次的博客又过去了一个多月,经过一段时间对Java的学习我们也迎来了期末考试了。这几次pta是期末前的最后几次pta,考察了菜单程序和课程程序,难度较之前有所提升,在下面分析一下。2.设计与分析7-1菜单计价程序-5首先是这道题,本题在菜单计价程序-3的基础上增加了部分内容,......
  • PTA7-11总结
     一.前言PTA-7考察了菜单计价程序的迭代,主要考察类的基本结构设计,对输入字符串进行处理,对输入时间的处理,以及对输入的不同类型的菜品数据分类处理,难点在于输入数据的处理和判断输入异常,难度一般,题量少。PTA-8考察了课程成绩统计程序的第一次,主要考察一些类基本的结构设计,一些......
  • 题目集7~11的总结性Blog
    一、前言(1)pta第七次作业题目列表如下:7-1 菜单计价程序-5总结:这个菜单计价1程序-5是前菜单计价程序-3的迭代,难度较之前的有所提升,题目难度对我来说感觉很大,写了很久也没有拿下。(2)pta第八次作业题目列表如下:7-1课程成绩统计程序-1总结:总算是熬过了菜单,迎来了新的课......
  • oop题目集7~11的总结性Blog
    目录一、前言二、设计与分析:一、前言4~6的训练集难度较上一次提升很多,训练了很多java中独有的提供好的方法,如hashset,数组的sort等方法,实现了代码运行时间的优化,和内存的占用减少,学会了代码的封装,和使用类间关系,同时了解并使用了正则表达式,了解Scanner类中nextLine()等方法、Str......
  • 【ubuntu22.04】设置了共享文件夹但是在虚拟机中找不到/mnt/hgfs文件夹的问题
    【ubuntu22.04】设置了共享文件夹但是在虚拟机中找不到/mnt/hgfs文件夹的问题问题描述vmware设置了共享文件夹,并且设置文件夹权限后,在虚拟机中找不到共享文件夹解决步骤:1、设置共享文件夹首先vmware-workstation需要安装Vmwaretools工具,我这里已经安装了,然后在Vmware菜单......