如何正确从连接表中选择字段?

问题描述 投票:0回答:5

这是我的简化模型,我已经加入了模型:

class Apartment < ApplicationRecord
  has_many :towers
end

class Tower < ApplicationRecord
  belong_to :apartment
end

然后我尝试在控制器中加入两个表。我也在 Rails 控制台中尝试过,如下所示:

Apartment.joins(:towers).select('apartments.id', 'apartments.name', 'towers.id' , 'towers.name')

问题是上面的查询只返回

公寓.id 和公寓.名称

也尝试过使用这样的别名,仍然没有成功

Apartment.joins(:towers).select('apartments.id', 'apartments.name',
'towers.id as towerid' , 'towers.name as towername')

我已确认所有塔楼都有公寓,我知道我可以这样做以获得 1 条记录

Apartment.joins(:towers).select('公寓.id', '公寓.name', 'towers.id' , 'towers.name').first.towers.id

等等,但我需要所有记录和所有这些字段,请提出建议。

这是我在 Rails 控制台中得到的最新结果:

 Apartment Load (1.0ms)  SELECT apartments.id, apartments.name, towers.id as towerid, towers.
    tower_name as towername FROM `apartments` INNER JOIN `towers` ON `towers`.`apt_id` = `
    apartments`.`id`
    => #<ActiveRecord::Relation [#<Apartment id: 5, name: "basura">, #<Apartment id: 5, apt_
    name: "basura">, #<Apartment id: 124, name: "hydra">, #<Apartment id: 124, name: "hy
    dra">, #<Apartment id: 126, name: "mediterania">, #<Apartment id: 126, name: "mediterania">, #<Apartment id: 142, name: "apartement gajah mada">, #<Apartment id: 142, name: "apartement gajah mada">]>

如你所见,上面的查询只返回2个字段,我需要的结果是这样的:

#<Apartment id: 126, name: "mediterania", tower_id: 12, tower_name: "tower A">, 
#<Apartment id: 126, name: "mediterania", tower_id: 15, tower_name: "tower F">

等等...

ruby-on-rails ruby-on-rails-4 activerecord rails-activerecord
5个回答
26
投票

我认为这是可能的唯一方法是使用

as

q = Apartment.joins(:towers).select('apartments.id, apartments.name, towers.id as t_id, towers.name as t_name')

q.first.t_id
q.first.t_name

为什么first.towers.id不起作用?

apartment.towers
将会返回
ActiveRecord::Associations::CollectionProxy
。您可以将其视为塔的集合。在 SQL 查询中,您指的是
towers
表。但是当你运行apartment.towers.id时,你正在CollectionProxy对象上调用id,这是行不通的。您可以使用
towers.first
获得第一座塔。

关于,

Apt Load (1.0ms)  SELECT apts.id, apts.apt_name, towers.id as towerid, towers.
    tower_name as towername FROM `apts` INNER JOIN `towers` ON `towers`.`apt_id` = `
    apts`.`id`
    => #<ActiveRecord::Relation [#<Apt id: 5, apt_name: "basura">, #<Apt id: 5, apt_
    name: "basura">, #<Apt id: 124, apt_name: "hydra">, #<Apt id: 124, apt_name: "hy
    dra">, #<Apt id: 126, apt_name: "mediterania">, #<Apt id: 126, apt_name: "mediterania">, #<Apt id: 142, apt_name: "apartement gajah mada">, #<Apt id: 142, apt_name: "apartement gajah mada">]>

在控制台看到的是

inspsect
方法返回的结果。
inspect
方法并不是为了显示非列属性而设计的。因此,即使内存中有 towername,它也只会显示公寓模型的列属性。
更多关于检查

我还建议尝试以下方法:

Apartment.joins(:towers).pluck('apartments.id, apartments.name, towers.id as t_id, towers.name as t_name')

以上语句将获取数组中的所有数据。使用 select 得到的结果相同,但 select 不会加载数组中的所有数据。


12
投票

你应该使用

Apartment.joins(:towers).select('apartments.id, apartments.name, towers.id , towers.name')

这是单个字符串内的所有列名称。

参考这个。


4
投票

Rails 7.1 添加对此类查询的支持,现在

select
接受哈希

您可以像这样使用别名

Apartment
  .joins(:towers)
  .select(
    apartments: { id: :apartment_id, name: :apartment_name },
    towers: { id: :tower_id, name: :tower_name }
  )

它产生这样的查询

SELECT apartments.id AS apartment_id, apartments.name AS apartments_name,
  towers.id AS tower_id, towers.name AS tower_name
FROM apartments
INNER JOIN towers ON towers.apartment_id = apartments.id

0
投票

您可以尝试使用如下的别名

Apartment.joins(:towers).select('apartments.id as apartment_id, apartments.name as apartment_name, towers.id as tower_id , towers.name as tower_name)

0
投票

你可以试试这个

Apartment.joins(:towers).select('apartments.id 作为 id, 公寓.name 作为 Apartment_name, towers.id 作为 tower_id , towers.name 作为 tower_name)

你会得到这样的回复 #ActiveRecord::关系 [#, #]>

© www.soinside.com 2019 - 2024. All rights reserved.