Как left join работает с sqlx

Я пытаюсь внутренне объединить две таблицы 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}}
]

Я не могу понять, что пошло не так.

Вы не можете иметь несколько столбцов с одинаковым именем в наборе результатов, это просто функция mysql cli, которая обрабатывает его

zerkms 03.10.2018 09:22

Ладно, я не знаю, как это сделать. Я пробовал использовать profile.id as profile_id вместо profile.id, но это не сработало. Вы можете мне еще немного помочь?

dakait 03.10.2018 09:29

Я погуглил "go sqlx join select", и это первый результат: snippets.aktagon.com/snippets/…

zerkms 03.10.2018 09:32

Нет ничего уникального в левом соединении (или любом соединении) в sqlx. sqlx просто обрабатывает строки, возвращаемые вашей базой данных - логика этого запроса на 100% не имеет отношения к sqlx.

Flimzy 03.10.2018 09:38
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
1
4
2 989
3

Ответы 3

Вам нужно изменить имя 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, наиболее близок к моему запросу, и он действительно решил мою проблему.

dakait 03.10.2018 15:16

вам не нужно ничего менять в базе данных, вам нужно просто изменить структуру Person, например, здесь я говорю о Id int64 ``db:"pId", этот db на самом деле вам нужно изменить.

saddam 03.10.2018 15:26

Ошибка связана с возвратом двух столбцов 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

Другие вопросы по теме