感到shoe角:在gorm中使用joins

时间:2018-09-05 14:23:31

标签: orm go-gorm

免责声明:这是我第一次使用ORM,并且我的SQL可能有点生疏。

我有一个带有用户,歌曲的应用程序,我想统计并显示给定用户播放每首歌曲的次数。我知道如何使用SQL进行操作,但是无法将其转换为GORM。它是这样的:

package main

import (
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/sqlite"
)

type User struct {
    ID       int `gorm:"primary_key"`
    Listened []Listen
}

type Song struct {
    ID       int `gorm:"primary_key"`
    Title    string
    Listened []Listen
}

type Listen struct {
    UserID int `gorm:"primary_key;auto_increment:false"`
    SongID int `gorm:"primary_key;auto_increment:false"`
    Count  int
}

然后,我们添加一些数据

func main() {
    db, err := gorm.Open("sqlite3", "test.db")
    if err != nil {
        panic(err)
    }
    defer db.Close()

    db.DropTableIfExists(&User{}, &Song{}, &Listen{})
    db.CreateTable(&User{}, &Song{}, &Listen{})

    db.Save(&User{ID: 1})
    db.Save(&User{ID: 2})

    db.Save(&Song{ID: 1, Title: "oh yeah"})
    db.Save(&Song{ID: 2, Title: "greatest song"})
    db.Save(&Song{ID: 3, Title: "bestest song"})

    db.Save(&Listen{UserID: 1, SongID: 1, Count: 7})
    db.Save(&Listen{UserID: 1, SongID: 2, Count: 23})
    db.Save(&Listen{UserID: 2, SongID: 2, Count: 13})
    db.Save(&Listen{UserID: 2, SongID: 3, Count: 10})

    // do something here
}

现在,正如我所说,我想列出用户播放数据库中每首歌曲的次数。挠了一下头后,我来到了这个地方:

sqlite> select songs.id, l.count from songs
   ...> left join (select song_id, count from listens where user_id = 1) as l
   ...> on songs.id = l.song_id;
id          count     
----------  ----------
1           7         
2           23        
3

...我在这里。我只是不明白如何使用GORM方法链来表达这一点。还是应该放弃并运行原始sql查询?

2 个答案:

答案 0 :(得分:0)

最后,我找到了怎么做:

db.Table("songs"). Select("songs.id, listens.count"). Joins("left join (select * from listens where user_id = ?) as listens on songs.id = listens.song_id", 1). Find(&rs)

答案 1 :(得分:0)

此查询可能也将起作用。希望对您有所帮助。

if err := db.Table("listens").Select("songs.id, listens.count").
Joins("JOIN songs on listens.song_id = songs.id").Where("user_id = ?", 
1).Find(&rs).Error; err != nil {
    fmt.Prinln(err)
}