2017-01-09 2 views
1

У меня есть 3 таблицы, которые представляют многие отношения. клиентов, компаний, компаний.Построение go-pg ORM-запроса для отношения многих ко многим

companies: 
- id 
- name 

customers: 
- id 
- username 

companies_customers: 
- id 
- customer_id 
- company_id 

Теперь запрос я хочу запустить, чтобы выбрать все клиенты с company_id из 1. Исходный SQL-запрос может/может выглядеть примерно так:

SELECT * FROM customers c INNER JOIN customers_companies cc ON c.id = cc.customer_id WHERE cc.company_id = 1 

Я пытался делать что-то вроде этого в ходу-пг:

var customers []*Customer 

s.DB.Model(&customers).Relation("Companies", func(q *orm.Query) (*orm.Query, error) { 
    return q.Where("company_id = ?", companyID), nil 
}).Select() 

ответ

1

в данном конкретном случае, вы можете сделать некоторые обходной путь, чтобы выполнить этот конкретный запрос, я полагаю, у вас есть тезисы структуры:

type Company struct { 
    TableName struct{} `sql:"companies"` 
    ID  int64 
    Name  string 
    Customers []*Customer `pg:",many2many:companies_customers"` 
} 

type Customer struct { 
    TableName struct{} `sql:"customers"` 
    ID  int64 
    Username string 
    Companies []*Company `pg:",many2many:companies_customers"` 
} 

Если вам нужно только выполнить запрос с JOIN, вы можете сделать

var customers []*Customer 
err := conn.Model(&customers).Column("customer.*").Join("inner join companies_customers cc on customer.id = cc.customer_id").Where("cc.company_id = ?", companyID).Select() 
if err != nil { 
    // Error Handler 
} else { 
    for _, customer := range customers { 
     fmt.Printf("Customer -> id: %d, username:%s \n", customer.ID, customer.Username) 
    } 
} 

Это генерировать:

SELECT "customer".* FROM customers AS "customer" inner join companies_customers cc on customer.id = cc.customer_id WHERE (cc.company_id = 1) 

Но, вы также можете сделать следующее:

var customers []*Customer 
var company Company 
err = conn.Model(&company).Column("Customers").Where("company.id = ?", companyID).Select() 
if err != nil { 
    // error handler 
} else { 
    customers = company.Customers 
    for _, customer := range company.Customers { 
     fmt.Printf("Customer -> id: %d, username:%s \n", customer.ID, customer.Username) 
    } 
} 

Этот код выполняет два запроса:

SELECT "company"."id", "company"."name" FROM companies AS "company" WHERE (company.id = 1) 
SELECT companies_customers.*, "customer".* FROM customers AS "customer" JOIN companies_customers ON (companies_customers."company_id") IN ((1)) WHERE ("customer"."id" = companies_customers."customer_id") 

Сначала создайте запрос для извлечения данных из company, после чего, принеси все клиенты этой компании.

+0

какой из двух вы бы сказали более эффективно? – Rodrigo

+0

@Rodrigo, если вы ищете эффективность, первый вариант лучше, потому что вы выполняете только один запрос, но вам нужно написать свое соединение самостоятельно. – Motakjuq

Смежные вопросы