【问题标题】:Joins with multiple tables/constraints OR has_one_through with secondary constraint连接多个表/约束或 has_one_through 与辅助约束
【发布时间】:2018-07-06 11:20:19
【问题描述】:

我为这个人为的例子道歉

一个person 有一个journey,但不直接连接到journey,而是通过houseoffice 连接。

一个person belongs_to a house,一个house has_many people

一个person belongs_to a office,一个office has_many people

一个journey belongs_to a house,一个house has many journeys

一个journey belongs_to a office,一个office has many journeys

                         +---------+
       +---Belongs-To---->         <----Belongs-To--+
       |                 |  House  |                |
       |  +-Has-Many-----+         +-----Has-Many-+ |
       |  |              +---------+              | |
       |  |                                       | |
+------+--v+                                     +v-+--------+
|          |                                     |           |
|  Person  |                                     |  Journey  |
|          |                                     |           |
+------+--^+                                     +^-+--------+
       |  |                                       | |
       |  |              +----------+             | |
       |  +-Has-Many-----+          +----Has-Many-+ |
       |                 |  Office  |               |
       +----Belongs-To--->          <---Belongs-To--+
                         +----------+

按照那个人为的例子,允许以下内容的最佳方法是什么:

person.journey 

或使用带有多个表的 Join 查询(使用 ruby​​ 哈希)或使用带有额外表约束的 has_one_through

我们确实有一个 sql 查询,但如果可以,我们宁愿避免使用原始 sql,但它看起来像这样:

Person
.joins('INNER JOIN journeys
        ON journeys.office_id = person.office_id
        AND journeys.house_id = person.house_id')

【问题讨论】:

  • 一个person属于一个office,而office有很多journeys。所以,在我看来,person 可以有多个journeys。它不应该是person.journey,而更像是person.journeys。甚至通过house 的关联也证实了这一点。
  • 当通过officehouse 完成时,你是对的,但是当通过这两个完成时,每个person 只有一个journey

标签: sql ruby postgresql activerecord ruby-on-rails-5.1


【解决方案1】:

很抱歉,我必须使用答案来获取更多信息。 这种情况下可以吗?

| Person                      |   | Journey                     |
|----+-----------+------------|   |----+-----------+------------|
| id | office_id | house_id   |   | id | office_id | house_id   |
|----+-----------+------------|   |----+-----------+------------|
| 1  | 1         | 1          |   | 1  | 1         | 1          |
| 2  | 1         | 1          |   | 2  | 1         | 1          |
| 3  | 1         | 1          |   | 3  | 1         | 1          |
| 4  | 1         | 1          |   | 4  | 1         | 1          |

如何从这个案例的数据中找到特定人的旅程?

如果您考虑person = Person.find(1) 并使用person.office_idperson.house_id 作为键在Journey 表中查找,您将获取ID 1、2、3 和4。不仅仅是一个旅程。

根据您的回复,这种情况永远不会发生,因为验证过滤器不允许。 因此,需要使用双外键访问 Journey 表:office_idhouse_id

最好的解决办法是

class Person < ActiveRecord::Base
  belongs_to :office
  belongs_to :house

  has_one :journey, foreign_keys: [:house_id, :office_id]

end

但 Rails 尚不支持多个外键。

一种可能的解决方法是为Person 类定义实例方法journey

class Person < ActiveRecord::Base
  belongs_to :office
  belongs_to :house

  def journey
    Journey.where(office_id: office_id, house_id: house_id).last
  end

end

所以你可以拨打person.journey

【讨论】:

  • A person 有一个 journey 因为 personjourney 只能同时拥有一个 office_idhouse_id,方法是将 person 匹配到 @987654339 @ 由他们共享的office_idhouse_id,您可以将journeyperson 匹配。
  • 如果有帮助,我将重命名这些示例,但在这种情况下,一个人和旅程永远不能被分配到办公室或房子一次,我意识到这是一个人为的例子(正如我所说)但这就是这个特定系统的设计方式。
  • 也许我遗漏了一些东西。但如果你看看我的情况:-1-没有人拥有超过一个办公室; -2- 没有人拥有超过一所房子; -3- 没有旅程有超过一个办公室; -4- 没有旅程不止一所房子。我的案件数据如何找到特定人的旅程? (我编辑了我的帖子)。
  • 这种情况永远不会发生,有一个唯一性验证,我确实说过这是一个人为的例子,但基础是一样的,我想我应该用其他词来举例。
  • 好吧,如果您想将我的表格粘贴到您的原始帖子中,请根据可能的真实数据更改office_idhouse_id 值并添加查询的预期结果,也许有人或者我自己可以尝试提供帮助;)
猜你喜欢
  • 2017-08-25
  • 2017-10-23
  • 1970-01-01
  • 2011-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多