// 简单的子查询 db.Where("amount > (?)", db.Table("orders").Select("AVG(amount)")).Find(&orders) // SQL: SELECT * FROM "orders" WHERE amount > (SELECT AVG(amount) FROM "orders");
// 内嵌子查询 subQuery := db.Select("AVG(age)").Where("name LIKE ?", "name%").Table("users") db.Select("AVG(age) as avgage").Group("name").Having("AVG(age) > (?)", subQuery).Find(&results) // SQL: SELECT AVG(age) as avgage FROM `users` GROUP BY `name` HAVING AVG(age) > (SELECT AVG(age) FROM `users` WHERE name LIKE "name%")
From 子查询
GORM 允许在 FROM 子句中使用子查询,从而支持复杂的查询和数据组织。
1 2 3 4 5 6 7 8 9
// 在 FROM 子句中使用子查询 db.Table("(?) as u", db.Model(&User{}).Select("name", "age")).Where("age = ?", 18).Find(&User{}) // SQL: SELECT * FROM (SELECT `name`,`age` FROM `users`) as u WHERE `age` = 18
// 在 FROM 子句中结合多个子查询 subQuery1 := db.Model(&User{}).Select("name") subQuery2 := db.Model(&Pet{}).Select("name") db.Table("(?) as u, (?) as p", subQuery1, subQuery2).Find(&User{}) // SQL: SELECT * FROM (SELECT `name` FROM `users`) as u, (SELECT `name` FROM `pets`) as p
GORM 提供了灵活的数据查询,允许将结果扫描进(scanned into)map[string]interface{} or []map[string]interface{},这对动态数据结构非常有用。
当使用 Find To Map时,一定要在你的查询中包含 Model 或者 Table ,以此来显式地指定表名。 这能确保 GORM 正确的理解哪个表要被查询。
1 2 3 4 5 6 7 8 9
// 扫描第一个结果到 map with Model 中 result := map[string]interface{}{} db.Model(&User{}).First(&result, "id = ?", 1) // SQL: SELECT * FROM `users` WHERE id = 1 LIMIT 1
// 扫描多个结果到部分 maps with Table 中 var results []map[string]interface{} db.Table("users").Find(&results) // SQL: SELECT * FROM `users`
// 如果没找到 name 为 "non_existing" 的 User,就初始化一个新的 User var user User db.FirstOrInit(&user, User{Name: "non_existing"}) // user -> User{Name: "non_existing"} if not found
// 检索名为 “jinzhu” 的 User db.Where(User{Name: "jinzhu"}).FirstOrInit(&user) // user -> User{ID: 111, Name: "Jinzhu", Age: 18} if found
// 使用 map 来指定搜索条件 db.FirstOrInit(&user, map[string]interface{}{"name": "jinzhu"}) // user -> User{ID: 111, Name: "Jinzhu", Age: 18} if found
// 如果没找到 User,根据所给条件和额外属性初始化 User db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrInit(&user) // SQL: SELECT * FROM USERS WHERE name = 'non_existing' ORDER BY id LIMIT 1; // user -> User{Name: "non_existing", Age: 20} if not found
// 如果名为 “Jinzhu” 的 User 被找到,`Attrs` 会被忽略 db.Where(User{Name: "Jinzhu"}).Attrs(User{Age: 20}).FirstOrInit(&user) // SQL: SELECT * FROM USERS WHERE name = 'Jinzhu' ORDER BY id LIMIT 1; // user -> User{ID: 111, Name: "Jinzhu", Age: 18} if found
// 根据所给条件和分配的属性初始化,不管记录是否存在 db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrInit(&user) // user -> User{Name: "non_existing", Age: 20} if not found
// 如果找到了名为“Jinzhu”的用户,使用分配的属性更新结构体 db.Where(User{Name: "Jinzhu"}).Assign(User{Age: 20}).FirstOrInit(&user) // SQL: SELECT * FROM USERS WHERE name = 'Jinzhu' ORDER BY id LIMIT 1; // user -> User{ID: 111, Name: "Jinzhu", Age: 20} if found
// 对指定索引提供建议 db.Clauses(hints.UseIndex("idx_user_name")).Find(&User{}) // SQL: SELECT * FROM `users` USE INDEX (`idx_user_name`)
// 强制对JOIN操作使用某些索引 db.Clauses(hints.ForceIndex("idx_user_name", "idx_user_id").ForJoin()).Find(&User{}) // SQL: SELECT * FROM `users` FORCE INDEX FOR JOIN (`idx_user_name`,`idx_user_id`)
// Scope for filtering records where amount is greater than 1000 funcAmountGreaterThan1000(db *gorm.DB) *gorm.DB { return db.Where("amount > ?", 1000) }
// Scope for orders paid with a credit card funcPaidWithCreditCard(db *gorm.DB) *gorm.DB { return db.Where("pay_mode_sign = ?", "C") }
// Scope for orders paid with cash on delivery (COD) funcPaidWithCod(db *gorm.DB) *gorm.DB { return db.Where("pay_mode_sign = ?", "COD") }
// Scope for filtering orders by status funcOrderStatus(status []string)func(db *gorm.DB) *gorm.DB { returnfunc(db *gorm.DB) *gorm.DB { return db.Where("status IN (?)", status) } }
// 计数 有着特定名字的 users db.Model(&User{}).Where("name = ?", "jinzhu").Or("name = ?", "jinzhu 2").Count(&count) // SQL: SELECT count(1) FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2'
// 计数 有着单一名字条件(single name condition)的 users db.Model(&User{}).Where("name = ?", "jinzhu").Count(&count) // SQL: SELECT count(1) FROM users WHERE name = 'jinzhu'
// 在不同的表中对记录计数 db.Table("deleted_users").Count(&count) // SQL: SELECT count(1) FROM deleted_users
配合 Distinct 和 Group 使用 Count
GORM还允许对不同的值进行计数并对结果进行分组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// 为不同 name 计数 db.Model(&User{}).Distinct("name").Count(&count) // SQL: SELECT COUNT(DISTINCT(`name`)) FROM `users`
// 使用自定义选择(custom select)计数不同的值 db.Table("deleted_users").Select("count(distinct(name))").Count(&count) // SQL: SELECT count(distinct(name)) FROM deleted_users