【问题标题】:How left join works with sqlx左连接如何与 sqlx 一起工作
【发布时间】:2019-03-08 08:55:07
【问题描述】:

我正在尝试通过一个简单的查询来内部连接两个表personprofile,这似乎适用于mysql,但不适用于sqlx。 这是我的代码:

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 程序没有按预期响应。该结构无法捕获配置文件 ID(输出中为空),并且人员 ID 被替换为配置文件 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}}
]

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

【问题讨论】:

  • 结果集中不能有多个同名的列,它只是 mysql cli 处理它的功能
  • 好吧,我不知道怎么做。我尝试使用profile.id as profile_id 而不是profile.id,但它没有用。你能给我提供更多帮助吗?
  • 我用谷歌搜索“go sqlx join select”,这是第一个结果:snippets.aktagon.com/snippets/…
  • sqlx 中的左连接(或任何连接)绝对没有什么独特之处。 sqlx 只处理数据库返回的行——查询背后的逻辑与 sqlx 100% 无关。

标签: mysql go sqlx


【解决方案1】:

按照@zerkms 提供的sn-p,我做了一些更改,使我可以运行程序而不会出错,也不会重命名db 标签。 首先,我在配置文件结构中添加了以下代码,以让查询识别人员结构

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指出的重复列名

【讨论】:

    【解决方案2】:

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

    传递多列但不同的列名称,您可以将其用作别名。列别名将是您正在扫描数据的 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)
    

    【讨论】:

      【解决方案3】:

      您需要更改person 结构中的db 名称,如下所示,因为将有两列具有相同名称,即id,因此它只扫描您profile 表中的最后一个ID而不是扫描person 表,所以按照下面提到的结构。

      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")
      

      【讨论】:

      • 我无法更改数据库名称,因为我正在使用现有数据库。我发现@zerkms 提供的 sn-p 最接近我的查询,它确实解决了我的问题。
      • 您不需要更改数据库中的任何内容,您只需更改 struct Person 就像这里我说的是 Id int64 ``db:"pId" ,这个 db 实际上你需要更改。跨度>
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-10-24
      • 2011-02-18
      • 1970-01-01
      • 2015-11-17
      • 2019-08-29
      • 2023-03-28
      • 1970-01-01
      相关资源
      最近更新 更多