Rails has_many, где связанная запись соответствует критерию - PullRequest
0 голосов
/ 28 октября 2018

В этой (упрощенной) системе

class Order
  has_one :bill
  ...
end


class Bill
  has_many :rebills
  belongs_to :order

  ...
end

class Rebill
  belongs_to :bill
  ...
end

И Bill, и Rebill имеют столбец status, который может находиться в одном из множества состояний, некоторые равны успеху инекоторые из них равны неудаче.

В настоящее время я пытаюсь найти все записи Order, которые не имеют какой-либо успешной оплаты.Заказ соответствует моим критериям, если соответствующая запись Bill находится в состоянии сбоя и что Bill записи имеют нет связанных Rebill записей, которые находятся в успешном состоянии.

Если у Order есть Bill, который вышел из строя, Rebill, который также не прошел, и вторая Rebill, которая прошла успешно, тогда Order выплачено, и я незаинтересованы в этом.

Если Order имеет Bill, который не прошел, и не связан Rebills, то у него нет успешного платежа, и я am заинтересован в нем.

Если у Order есть Bill, который вышел из строя, и любое число Rebills в состоянии сбоя (но не одно в успешном состоянии), то нет успешного платежа, и я am заинтересован в этом.

Поэтому мой вопрос: как построить запрос, который возвращает все Order записи, которые не имеют какой-либо успешный платеж?Реальная проблема здесь заключается в том, что я держу понятие успешного платежа в нескольких местах, что плохо.Тем не менее, я чувствую, что я должен быть в состоянии шептать правильное заклинание SQL, чтобы сделать это, но число объединений, где, наличие и количество вводит меня в заблуждение до предела!

Любой, кто-либо знает, что япытаясь сделать здесь, и если да, то есть мысли, как я могу это сделать?

Ответы [ 2 ]

0 голосов
/ 28 октября 2018

Примерно так должно работать.

# rebills contains all rebills with a successful payment
rebills = Rebill.where(status: 'successful')
# bills contains bills without a successful payment
# that are not associated with the above described rebills 
bills = Bill.where.not(status: 'successful', id: rebills.select(:bill_id))
# orders contains orders that are associated with the above described bills
orders = Order.where(id: bills.select(:order_id))

При загрузке orders вышеприведенное должно выполнить один запрос.

Примечание: При копированиив суффиксе консоли строки с ;nil для предотвращения метода inspect (который используется для отображения возвращаемого значения консоли) для загрузки коллекций.

0 голосов
/ 28 октября 2018

Это не так сложно.Прежде всего, давайте найдем все Order записи, которые имеют Bill запись в состоянии сбоя.

Order.joins(:bill).where(bills: { state: "failed" })

Теперь давайте удостоверимся, что для Bill не существует Rebill вуспешное состояние:

Order.joins(:bill).where(bills: { state: "failed" })
     .where("NOT EXISTS(SELECT 1 FROM rebills 
                        WHERE bill_id = bills.id 
                        AND rebills.state = successful)")

Возможно, вы сможете написать запрос NOT EXISTS более активным способом, я обычно сдаюсь и обращаюсь к сырому SQL.

БДСкрипка прилагается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...