ActiveRecord - 查询与多个条件对的关联

时间:2017-07-16 07:11:48

标签: ruby-on-rails postgresql ruby-on-rails-4 activerecord

这是一个带有小型数据库模式的上下文

Order
  -> id
LineItem
  -> id
  -> order_id
Transaction
  -> id
  -> transaction_type
  -> successful
  -> line_item_id

基本上,我们要做的是获取所有包含多笔交易的订单,匹配交易中的特定条件对

这是一个非常基本的表模式,用作示例:

Order (orders)
+----+
| id | 
|----|
|  1 |
|  2 | <--
|  3 |

Line Items (line_items)
+---------------+
| id | order_id |
|----|----------|
| 1  | 1        |
| 2  | 2        | <--
| 3  | 3        |

Transactions (transactions)
+---------------------------------------------------+
| id | transaction_type | successful | line_item_id |
|----|------------------|------------|--------------|
| 1  | 2                | 1          | 1            |
| 2  | 2                | 0          | 2            | <--
| 3  | 1                | 1          | 1            |
| 4  | 3                | 1          | 2            | <--
| 5  | 1                | 1          | 3            |
| 6  | 3                | 1          | 3            |

我用箭头突出显示了我们将关注的记录。

Order类可以在上下文中添加更多内容:

class Order < ActiveRecord::Base
    has_many :line_items
    has_many :transactions, through: :line_items
end

正如我所说,我们希望通过transactions上的特定约束(对)获取所有订单。

因此,如果我们有order

,我们只想选择一个(At least ONE transaction with "transaction_type" = 2 AND "successful = 0"), AND (At least ONE transaction with "transaction_type" = 3 AND "successful" = 1)

不能OR。只有在尊重两个约束对时才应选择顺序。

(示例:我只想要订单,其中的订单项只有一个类型为2的交易且不成功)。 [这应该只给我订单,其中包含具有单一交易类型的订单项,但它可以包含任何其他类型的交易]

我在过去的10个小时里一直在寻找如何实现这一点,但无济于事,所以我求助于你。 如果您感到好奇:我们使用postgres

我甚至不知道从哪里开始查询,甚至更少知道ActiveRecord语法。

问题的好例子: https://github.com/dsounded/ransack_example/blob/master/app/services/finder.rb#L7 这个问题是无法对结果进行排序或分页。

2 个答案:

答案 0 :(得分:1)

您可以尝试自行加入交易

Transactions.joins("INNER JOIN transactions as x ON x.line_item_id=transactions.line_item_id").where("transactions.transaction_type=2 AND transactions.successful=0").where("x.transaction_type=3 AND x.successful=1").includes(:order)

答案 1 :(得分:0)

您需要使用havingwhere的联接,例如:

    Order.joins(line_items: :transactions).select("orders.*")
.group("orders.id").having(count(transactions.id) > 2).where(your conditions)