编程笔记

lifelong learning & practice makes perfect

Go|如何在gorm中使用Distinct

GORM 中 Distinct 用于从数据库查询中返回唯一不同的值。它有效地消除了结果集中的重复记录,只保留具有唯一指定字段值的记录。

以下是 Distinct 在 GORM 中的使用和效果:

基本用法:

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package main

import (
"fmt"
"log"

"gorm.io/driver/sqlite"
"gorm.io/gorm"
)

type User struct {
gorm.Model
Name string
City string
Email string
}

func main() {
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
log.Fatal("failed to connect database:", err)
}

// AutoMigrate the schema
db.AutoMigrate(&User{})

// Seed data (if needed)
users := []User{
{Name: "Alice", City: "New York", Email: "alice@example.com"},
{Name: "Bob", City: "Los Angeles", Email: "bob@example.com"},
{Name: "Charlie", City: "New York", Email: "charlie@example.com"},
{Name: "David", City: "Chicago", Email: "david@example.com"},
{Name: "Eve", City: "Los Angeles", Email: "eve@example.com"},
}
db.Create(&users)

// Find distinct cities
var distinctCities []string
result := db.Model(&User{}).Distinct("city").Pluck("city", &distinctCities)
if result.Error != nil {
log.Fatal("failed to query distinct cities:", result.Error)
}

fmt.Println("Distinct cities:", distinctCities) // Output: Distinct cities: [New York Los Angeles Chicago]

// You can also use it with a `Select` statement for more complex queries
var results []struct {
City string
Count int64
}

db.Model(&User{}).Select("city, count(*) as count").Group("city").Find(&results)
fmt.Println("City counts:", results)
// City counts: [{New York 2} {Los Angeles 2} {Chicago 1}]

// cleanup
db.Migrator().DropTable(&User{})

}

解释:

  1. Distinct("city"): 这个语句告诉 GORM 只返回 city 列中唯一不同的值。
  • 消除重复值: Distinct 确保结果集中没有重复的 city 值。 例如,即使数据库中有多个 “New York” 记录,结果集中也只会包含一个 “New York”。
  • 返回唯一值: 只返回指定列的唯一值。
  • 与其他 GORM 方法的组合: Distinct 可以与其他 GORM 方法结合使用,例如 WhereOrderLimit 等,以构建更复杂的查询。

高级用法和注意事项:

  • Multiple Columns: 你可以对多个列使用 Distinct,以获得基于多个列的唯一组合。

    1
    2
    3
    4
    5
    6
    7
    var distinctResults []struct {
    Name string
    City string
    }

    db.Model(&User{}).Distinct("name", "city").Find(&distinctResults)
    // This will find all unique combinations of name and city.
  • 数据库支持: Distinct 的行为可能略有不同,具体取决于你使用的数据库系统。 重要的是要理解底层数据库引擎如何处理 Distinct 查询。

  • 性能影响: Distinct 查询通常比非 Distinct 查询更慢,尤其是在大型数据集上。 这是因为数据库需要进行额外的排序或哈希操作来消除重复项。 如果性能是一个关键问题,请考虑以下几点:

    • 索引:Distinct 使用的列上创建索引可以提高查询性能。
    • 数据预处理: 如果可能,在数据插入或更新时消除重复项,以避免在查询时进行重复数据删除。
    • 数据结构优化: 考虑使用具有内置去重机制的数据结构(例如集合)来存储和处理数据。
    • 避免不必要的 Distinct: 只在确实需要唯一值时才使用 Distinct
  • SELECT * 的结合: 直接结合 SELECT *Distinct 的行为因数据库而异,通常你需要指定 Distinct 应用于哪些列。 在 GORM 中,通常避免直接在 SELECT * 上使用 Distinct,而是使用 ModelSelect 配合使用,或者使用结构体来接收结果。

  • NULL 值: Distinct 通常会将 NULL 值视为不同的值。 因此,如果某一列包含多个 NULL 值,Distinct 将返回单个 NULL 值。

总结:

Distinct 是 GORM 中一个有用的方法,可以用于从数据库查询中返回唯一不同的值。 但是,在使用 Distinct 时,请注意其潜在的性能影响,并根据你的具体需求和数据量选择最佳方法。 通过正确的使用和优化,Distinct 可以帮助你构建更有效、更简洁的数据库查询。

欢迎关注我的其它发布渠道

0 comments
Anonymous
Markdown is supported

Be the first person to leave a comment!