How left join works with sqlx

huangapple go评论92阅读模式
英文:

How left join works with sqlx

问题

我正在尝试使用一个简单的查询将两个表personprofile进行内连接,这个查询在mysql中似乎工作正常,但在sqlx中不起作用。
以下是我的Go代码:

package main 

import (
	"fmt"
	"github.com/jmoiron/sqlx"
	_ "github.com/go-sql-driver/mysql"
)

type Person struct {
	Id 		int64 	`db:"id"`
	Name 	string 	`db:"name"`
	Email	string 	`db:"email"`
}

type Profile struct {
	Id 			int64 	`db:"id"`
	Face 		string 	`db:"face"`
	Hair 		string 	`db:"hair"`
	Person
}

func main() {
	DB, err := sqlx.Connect("mysql", "root:hackinitiator@/dusk")
	if err == nil {
		fmt.Println("sucess!!")
	} 
	var q []Profile
	DB.Select(&q, "select person.id, person.name, person.email, profile.id, profile.face, profile.hair from profile left join person on person.id = profile.person_id")
	fmt.Println(q)
}

MySQL查询产生以下输出:

+------+------+---------+----+----------+--------+
| id   | name | email   | id | face     | hair   |
+------+------+---------+----+----------+--------+
|    1 | yoda | nomail  |  1 | round    | brown  |
|    5 | han  | nomail1 |  3 | circle   | red    |
|    6 | yun  | nomail2 |  4 | triangle | yellow |
|    7 | chi  | nomail3 |  5 | square   | green  |
+------+------+---------+----+----------+--------+

这是完全正常的,但我的Go程序没有按预期响应。结构体无法捕获profile id(输出为空),而person id被替换为profile id。以下是格式化后的输出:

[
{0 round brown {1 yoda nomail}} 
{0 circle red {3 han nomail1}} 
{0 triangle yellow {4 yun nomail2}} 
{0 square green {5 chi nomail3}}
]

我无法弄清楚出了什么问题。

英文:

I'm trying to inner join two tables person and profile with a simple query which seems to work fine with mysql but not with sqlx.
Here's my go code:

package main 

import (
	"fmt"
	"github.com/jmoiron/sqlx"
	_ "github.com/go-sql-driver/mysql"
)

type Person struct {
	Id 		int64 	`db:"id"`
	Name 	string 	`db:"name"`
	Email	string 	`db:"email"`
}

type Profile struct {
	Id 			int64 	`db:"id"`
	Face 		string 	`db:"face"`
	Hair 		string 	`db:"hair"`
	Person
}

func main() {
	DB, err := sqlx.Connect("mysql", "root:hackinitiator@/dusk")
	if err == nil {
		fmt.Println("sucess!!")
	} 
	var q []Profile
	DB.Select(&q, "select person.id, person.name, person.email, profile.id, profile.face, profile.hair from profile left join person on person.id = profile.person_id")
	fmt.Println(q)
}

The mysql query produces the following output:

+------+------+---------+----+----------+--------+
| id   | name | email   | id | face     | hair   |
+------+------+---------+----+----------+--------+
|    1 | yoda | nomail  |  1 | round    | brown  |
|    5 | han  | nomail1 |  3 | circle   | red    |
|    6 | yun  | nomail2 |  4 | triangle | yellow |
|    7 | chi  | nomail3 |  5 | square   | green  |
+------+------+---------+----+----------+--------+

which is perfectly fine but my go program is not responding as expected. The struct is unable to capture the profile id(empty in output) and person id is replaced with profile id. Below is the output(formatted):

[
{0 round brown {1 yoda nomail}} 
{0 circle red {3 han nomail1}} 
{0 triangle yellow {4 yun nomail2}} 
{0 square green {5 chi nomail3}}
]

I'm unable to figure out what went wrong.

答案1

得分: 1

根据@zerkms提供的代码片段,我做了一些更改,使得程序能够正常运行,而且无需重命名数据库标签。
首先,我在profile结构体中添加了以下代码,以便查询能够识别person结构体:

Person `db:"person"`

接着,我将SQL查询字符串更改为以下代码:

DB.Select(&q, `select person.id "person.id", person.name "person.name", person.email "person.email", profile.* from profile left join person on person.id = profile.person_id`)

这样可以避免重复的列名,正如@zerkms所指出的。

英文:

Following the snippet provided by @zerkms I made a few changes which allowed me to run the program without errors and without renaming db tags.
First, I added the below code in profile struct to let the query identify person struct

Person `db:"person"`

Following this I changed my SQL query string to the below code

DB.Select(&q, `select person.id "person.id", person.name "person.name", person.email "person.email", profile.* from profile left join person on person.id = profile.person_id`)

to avoid duplicate column names as pointed out by @zerkms

答案2

得分: 0

你需要按照我描述的方式更改person结构中的db名称,因为会有两个具有相同名称的列,即id,所以它只会扫描在你的profile表中的最后一个id,而不会扫描person表中的id,所以请按照下面提到的结构进行更改。

type Person struct {
    Id      int64   `db:"pId"`
    Name    string  `db:"name"`
    Email   string  `db:"email"`
}

然后在你的查询中使用asperson.id编写查询语句,如下所示:

DB.Select(&q, "select (person.id) as pId, person.name, person.email, profile.id, profile.face, profile.hair from profile left join person on person.id = profile.person_id")
英文:

You need to change db name in person struct like below i'm describing because there would be two column with same name i.e. id so it scan only last one id which is in your profile table and not scan of person table, so follow the struct as mentioned below.

type Person struct {
    Id      int64   `db:"pId"`
    Name    string  `db:"name"`
    Email   string  `db:"email"`
}

And then write your query with as for person.id like

DB.Select(&q, "select (person.id) as pId, person.name, person.email, profile.id, profile.face, profile.hair from profile left join person on person.id = profile.person_id")

答案3

得分: 0

错误是由于从结果返回两个 id 列,但将结果存储在具有相同字段名 id 的结构体中,你将该结构体的实例传递给了 DB.Select。尝试捕获单个 id 列并将其传递给结构体。

传递多个列,但使用不同的列名,你可以将其用作别名。列别名将作为 Person 结构体中的字段,你可以将数据扫描到其中,如下所示:

type Person struct {
    PersonId    int64   `db:"personId"`
    Name        string  `db:"name"`
    Email       string  `db:"email"`
}

var q []Profile
DB.Select(&q, "select person.id as personId, person.name, person.email, profile.id, profile.face, profile.hair from profile left join person on person.id = profile.person_id")
fmt.Println(q)
英文:

The error is due to returning two id columns from the result but storing the result in a struct with same field name id in both structs, whose instance you are passing to DB.Select. Try to capture single id column and pass it to struct.

Pass multiple columns but different columns name which you can use as an alias. The column alias name will be the field in the Person struct in which you are scanning the data as:

type Person struct {
    PersonId    int64   `db:"personId"`
    Name        string  `db:"name"`
    Email       string  `db:"email"`
}

var q []Profile
DB.Select(&q, "select person.id as personId, person.name, person.email, profile.id, profile.face, profile.hair from profile left join person on person.id = profile.person_id")
fmt.Println(q)

huangapple
  • 本文由 发表于 2018年10月3日 15:19:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/52621745.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定