rails:通过join table+查询两步关系有很多关系

enxuqcxy  于 2021-06-17  发布在  Mysql
关注(0)|答案(1)|浏览(334)

我正在努力改进我的数据库方案。目前我使用的是一个has\ mun-through结构,带有一个land model/table、shippingservice model/table和一个postzone model/table,连接land和shipping表。

我可以这样查询:

@shippingservices = @cart.available_shipping_services.includes(:lands, :postzones).where('postzones.land_id = ?', params[:id])

并得到一个给定的土地(国家)的所有航运服务。
但这样一来,我在postzone表中会有很多重复,维护起来相当困难。如果我能在有许多土地的区域收集土地,比将航运服务连接到一个区域要容易得多。就像在这个方案中:

在这种情况下,我如何查询给定土地的所有运输服务?
对于联接表,我将执行以下操作:

@shippingservices = @cart.available_shipping_services.joins(:lands => :zones).where('lands_zones_join.land_id = ?', params[:id])

这不起作用,因为我得到:

Mysql::Error: Unknown column 'lands_zones_join.zone_id' in 'where clause': SELECT `shippingservices`.* FROM `shippingservices` 
INNER JOIN `zones` ON `zones`.`id` = `shippingservices`.`zone_id` 
INNER JOIN `lands_zones` ON `lands_zones`.`zone_id` = `zones`.`id` 
INNER JOIN `lands` ON `lands`.`id` = `lands_zones`.`land_id` 
INNER JOIN `lands_zones` `zones_lands_join` ON `zones_lands_join`.`land_id` = `lands`.`id` 
INNER JOIN `zones` `zones_lands` ON `zones_lands`.`id` = `zones_lands_join`.`zone_id` 
WHERE (weightmin <= 50 AND weightmax >= 50 AND height >= 3 AND shippingservices.shippingcarrier = '1') AND (length >= 210 AND width >= 149) AND (lands_zones_join.zone_id = '2')

这有可能吗?我怎样才能让它工作?
提前谢谢!
更新
型号/发货服务.rb

class Shippingservice < ActiveRecord::Base
  belongs_to :zone
  has_many :lands, :through => :zone
end

应用程序/模型/区域.rb

class Zone < ActiveRecord::Base
  has_and_belongs_to_many :lands, :join_table => "lands_zones"
  has_many :shippingservices
end

应用程序/模型/landszone.rb

class LandsZone < ActiveRecord::Base
  belongs_to :land
  belongs_to :zone
end

app/models/land.rb应用程序

class Land < ActiveRecord::Base
  has_and_belongs_to_many :zones, :join_table => "lands_zones"
  has_many :shippingservices, :through => :zones
end

数据库/架构.rb

create_table "lands", :force => true do |t|
  t.string   "name"
end

create_table "lands_zones", :force => true do |t|
  t.integer  "land_id"
  t.integer  "zone_id"
end

add_index "lands_zones", ["land_id"], :name => "index_lands_zones_on_land_id"
add_index "lands_zones", ["zone_id"], :name => "index_lands_zones_on_zone_id"

create_table "shippingservices", :force => true do |t|
  t.integer  "zone_id"
  t.string   "name"
  t.string   "shippingcarrier"
end

  create_table "zones", :force => true do |t|
    t.string   "name"
  end

我通过删除时间戳等来减少它,但保留了所有必要的部分。

gdx19jrr

gdx19jrr1#

@shippingservices = @cart.available_shipping_services.joins(:lands => :zones).where('lands_zones_join.land_id = ?', params[:id]) 这个 lands_zones_join where子句中的表不正确。rails将其视为一个派生表名,并应用两个额外的联接,如下所示:

INNER JOIN `lands_zones` `zones_lands_join` ON `zones_lands_join`.`land_id` = `lands`.`id` 
INNER JOIN `zones` `zones_lands` ON `zones_lands`.`id` = `zones_lands_join`.`zone_id`

这会导致查询结果重复。
关系来自 ShippingserviceLand 已在模型和架构中正确设置。因此,我们可以直接连接这些表,并查询lands表本身的id: @cart.available_shipping_services.joins(:lands).where(lands: {id: params[:id]})

相关问题