英文:
How left join works with sqlx
问题
我正在尝试使用一个简单的查询将两个表person
和profile
进行内连接,这个查询在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"`
}
然后在你的查询中使用as
为person.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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论