Я пытаюсь внутренне объединить две таблицы person и profile с помощью простого запроса, который, кажется, отлично работает с 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 не отвечает, как ожидалось. Структура не может захватить идентификатор профиля (пустой в выводе), и идентификатор человека заменяется идентификатором профиля. Ниже приведен результат (отформатированный):
[
{0 round brown {1 yoda nomail}}
{0 circle red {3 han nomail1}}
{0 triangle yellow {4 yun nomail2}}
{0 square green {5 chi nomail3}}
]
Я не могу понять, что пошло не так.
Ладно, я не знаю, как это сделать. Я пробовал использовать profile.id as profile_id вместо profile.id, но это не сработало. Вы можете мне еще немного помочь?
Я погуглил "go sqlx join select", и это первый результат: snippets.aktagon.com/snippets/…
Нет ничего уникального в левом соединении (или любом соединении) в sqlx. sqlx просто обрабатывает строки, возвращаемые вашей базой данных - логика этого запроса на 100% не имеет отношения к sqlx.






Вам нужно изменить имя db в структуре person, как показано ниже, потому что будет два столбца с одинаковым именем, то есть id, поэтому он сканирует только последний идентификатор, который находится в вашей таблице profile, а не сканирование таблицы person, поэтому следуйте структуре как указано ниже.
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")
Я не могу изменить имя базы данных, так как я работаю с уже существующей базой данных. Я считаю, что фрагмент, предоставленный @zerkms, наиболее близок к моему запросу, и он действительно решил мою проблему.
вам не нужно ничего менять в базе данных, вам нужно просто изменить структуру Person, например, здесь я говорю о Id int64 ``db:"pId", этот db на самом деле вам нужно изменить.
Ошибка связана с возвратом двух столбцов id из результата, но сохранением результата в структуре с тем же идентификатором имени поля в обеих структурах, экземпляр которой вы передаете в DB.Select. Попробуйте захватить столбец с одним идентификатором и передать его структуре.
Передайте несколько столбцов, но разные имена столбцов, которые вы можете использовать в качестве псевдонима. Псевдонимом столбца будет поле в структуре 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)
Следуя фрагменту, предоставленному @zerkms, я внес несколько изменений, которые позволили мне запустить программу без ошибок и без переименования тегов 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
Вы не можете иметь несколько столбцов с одинаковым именем в наборе результатов, это просто функция
mysqlcli, которая обрабатывает его