SQLによる取得結果をHas Manyの形で格納する方法【Go】
SQLの取得結果をHas Manyの形で格納したいことがあるかもしれません。しかし、SQLでのSELECTの結果は階層化されていないので、ソースコードでロジックを組んで組み立てる必要があります。
Goの場合、SQLの取得結果を1行ずつ処理できるrow.Next()があるので、用意した構造体に格納するロジックをソースコードで組めば、Has Manyを実現することができます。
type Group struct { GroupID int `json:"group_id"` GroupName string `json:"group_name"` Workers []Worker`json:"workers"` } type Worker struct { WorkerID int `json:"worker_id"` WorkerName string `json:"worker_name"` Jobs []Job`json:"jobs"` } type Job struct { JobID int `json:"job_id"` JobName string `json:"job_name"` } func main() { rtns := []*Group{} cnn := sql.Open("mysql", "...") rows, err := cnn.Query("SELECT ... FROM ...") for rows.Next() { group := &Group{} worker := &Worker{} job := &Job{} err := rows.Scan( &group.GroupID, &group.GroupName, &worker.WorkerID, &worker.WorkerName, &job.JobID, &job.JobName, ) if err != nil { ... return nil, err } rtns = buildGroups(rtns, group, worker, job) } return rtns, nil } // 前回のrowの内容と比較して、IDが一致する場合は前回のrowの格納結果のsliceに追加して階層構造を作る関数 func buildGroups(rtns []*Group, group *Group, worker *Worker, job *Job) []*Group { if len(rtns) > 0 { lastW := rtns[len(rtns)-1].Workers lastWorkerID := lastW[len(lastW)-1].WorkerID if worker.WorkerID == lastWorkerID { lastW[len(lastW)-1].Jobs = append(lastW[len(lastW)-1].Jobs, *job) } else { worker.Jobs = append(worker.Jobs, *job) lastGroupID := rtns[len(rtns)-1].GroupID if group.GroupID == lastGroupID { rtns[len(rtns)-1].Workers = append(lastW, *worker) } else { group.Workers = append(group.Workers, *worker) rtns = append(rtns, group) } } } else { worker.Jobs = append(worker.Jobs, *job) group.Workers = append(group.Workers, *worker) rtns = append(rtns, group) } return rtns }