Gorm 高级查询
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gorm 高级查询相关的知识,希望对你有一定的参考价值。
参考技术A 越高级,越复杂的查询,也同时意味着高耗,但是平时有一些数据少,但是业务复杂的场景,可以使用下。 这里主要说明的是 go 中使用 gorm 进务查询。有时候代码是可需要映射到一个 map 结构, 不需要映射到一个 结构体中,可以写成如下:
在涉及并发的场景,往往需要加锁互斥,和 Java 类似, Go 中也有加行锁的方式,加 for update 即可。
一般写法如下:
示例代码:
有时候,我们需要进行简单的数据统计, 比如查询到结果有多少行,
有时候也需要分组统计行数
有时候我们会使用到数据统计的功能, 比如根据数据库字段 batch_no 进行分组,然后统计总金额,总笔数。
分组查询统计一般的写法如下:
代码示例:
一般来说,很少使用关联查询,但是如果要使用关联查询,可以如下:
Scopes 允许你指定常用的查询,可以在调用方法时引用这些查询, 也就是说,可以在查询中使用函数。
举个例子:
在这里插入图片描述
如何在 Gorm 中留下连接子查询计数
【中文标题】如何在 Gorm 中留下连接子查询计数【英文标题】:How to left join subquery count in Gorm 【发布时间】:2021-12-19 21:03:32 【问题描述】:我希望我的 Gorm 查询返回正确的 version_count。我的 Gorm 查询返回 0 version_count,而我的 MySQL 查询返回 version_count。
我有下面的 MySQL 查询,用于将子查询计数连接到最终查询结果中。
我有这个用于我的 Gorm 查询:
subQuery := models.DB.Select("services.id as services_id, COUNT(versions.service_id) as version_count").Group("services.id").Preload("Versions").Table("Services").SubQuery()
models.DB.Preload("Versions").Find(&services).Count(&count).Limit(limit).Offset(offset).
Joins("LEFT JOIN (?) as version_counts ON version_counts.services_id = s.id", subQuery)
去结构
type Service struct
ID uint `json:"id" gorm:"primary_key"`
Name string `json:"name"`
Description string `json:"description"`
Versions []Version `json:"versions"`
VersionCount int `json:"version_count"`
CreatedAt string `json:"created_at"`
type Version struct
ID uint `json:"id" gorm:"primary_key"`
Version string `json:"name"`
ServiceID string `json:"service_id"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
有我的查询表。
mysql> select * from services;
+----+---------------------+---------------------+------------+--------+-------------+
| id | created_at | updated_at | deleted_at | name | description |
+----+---------------------+---------------------+------------+--------+-------------+
| 1 | 2021-11-05 21:16:25 | 2021-11-05 21:16:25 | NULL | John | New York |
| 2 | 2021-11-05 21:16:25 | 2021-11-05 21:16:25 | NULL | Martin | Los Angeles |
+----+---------------------+---------------------+------------+--------+-------------+
2 rows in set (0.02 sec)
mysql> select * from versions;
+----+---------------------+---------------------+------------+------------+---------+
| id | created_at | updated_at | deleted_at | service_id | version |
+----+---------------------+---------------------+------------+------------+---------+
| 1 | 2021-11-05 21:16:25 | 2021-11-05 21:16:25 | NULL | 1 | 1.0.0 |
| 2 | 2021-11-05 21:16:25 | 2021-11-05 21:16:25 | NULL | 1 | 1.0.1 |
| 3 | 2021-11-05 21:16:25 | 2021-11-05 21:16:25 | NULL | 1 | 1.0.2 |
| 4 | 2021-11-05 21:16:25 | 2021-11-05 21:16:25 | NULL | 2 | 1.0.0 |
| 5 | 2021-11-05 21:16:25 | 2021-11-05 21:16:25 | NULL | 2 | 1.0.1 |
| 6 | 2021-11-05 21:16:25 | 2021-11-05 21:16:25 | NULL | 2 | 1.0.2 |
| 7 | 2021-11-05 21:16:25 | 2021-11-05 21:16:25 | NULL | 2 | 1.0.3 |
+----+---------------------+---------------------+------------+------------+---------+
7 rows in set (0.01 sec)
mysql> select * from services s join versions v on v.service_id = s.id left join ( select s.id services_id, count(v.service_id) as version_count from services s join versions v on v.service_id = s.id group by s.id) version_counts ON version_counts.services_id = s.id;
+----+---------------------+---------------------+------------+--------+-------------+----+---------------------+---------------------+------------+------------+---------+-------------+---------------+
| id | created_at | updated_at | deleted_at | name | description | id | created_at | updated_at | deleted_at | service_id | version | services_id | version_count |
+----+---------------------+---------------------+------------+--------+-------------+----+---------------------+---------------------+------------+------------+---------+-------------+---------------+
| 1 | 2021-11-05 20:20:09 | 2021-11-05 20:20:09 | NULL | John | New York | 1 | 2021-11-05 20:20:09 | 2021-11-05 20:20:09 | NULL | 1 | 1.0.0 | 1 | 3 |
| 1 | 2021-11-05 20:20:09 | 2021-11-05 20:20:09 | NULL | John | New York | 2 | 2021-11-05 20:20:09 | 2021-11-05 20:20:09 | NULL | 1 | 1.0.1 | 1 | 3 |
| 1 | 2021-11-05 20:20:09 | 2021-11-05 20:20:09 | NULL | John | New York | 3 | 2021-11-05 20:20:09 | 2021-11-05 20:20:09 | NULL | 1 | 1.0.2 | 1 | 3 |
| 2 | 2021-11-05 20:20:09 | 2021-11-05 20:20:09 | NULL | Martin | Los Angeles | 4 | 2021-11-05 20:20:09 | 2021-11-05 20:20:09 | NULL | 2 | 1.0.0 | 2 | 4 |
| 2 | 2021-11-05 20:20:09 | 2021-11-05 20:20:09 | NULL | Martin | Los Angeles | 5 | 2021-11-05 20:20:09 | 2021-11-05 20:20:09 | NULL | 2 | 1.0.1 | 2 | 4 |
| 2 | 2021-11-05 20:20:09 | 2021-11-05 20:20:09 | NULL | Martin | Los Angeles | 6 | 2021-11-05 20:20:09 | 2021-11-05 20:20:09 | NULL | 2 | 1.0.2 | 2 | 4 |
| 2 | 2021-11-05 20:20:09 | 2021-11-05 20:20:09 | NULL | Martin | Los Angeles | 7 | 2021-11-05 20:20:09 | 2021-11-05 20:20:09 | NULL | 2 | 1.0.3 | 2 | 4 |
+----+---------------------+---------------------+------------+--------+-------------+----+---------------------+---------------------+------------+------------+---------+-------------+---------------+
7 rows in set (0.01 sec)
【问题讨论】:
【参考方案1】:我能够使用适当的 version_count 加载响应。
带有原始查询的 Gorm(更短更容易)
models.DB.Preload("Versions").Table("Services s").
Select("*").
Joins("left join (select s.id services_id, count(v.service_id) as version_count " +
"from services s " +
"join versions v on v.service_id = s.id " +
"group by s.id) version_counts " +
"ON version_counts.services_id = s.id").
Find(&services)
Gorm 查询(更复杂)
subQuery := models.DB.Debug().Table("Services s").
Select("s.id services_id, count(v.service_id) as version_count").
Joins("JOIN versions v ON v.service_id = s.id").Group("s.id").SubQuery()
models.DB.Debug().Preload("Versions").Table("Services s").
Select("*").
Joins("left join " +
"(" +
"?" +
") version_counts " +
"ON version_counts.services_id = s.id", subQuery).
Find(&services).Count(&count).Limit(limit).Offset(offset)
【讨论】:
以上是关于Gorm 高级查询的主要内容,如果未能解决你的问题,请参考以下文章