Преобразование SQL в Arel - столбец [...] должен появиться в предложении GROUP BY - PullRequest
0 голосов
/ 26 ноября 2018

У меня есть рабочий запрос SQL, и я хотел бы преобразовать его в Arel, но мне кажется, что я продолжаю сталкиваться с той же ошибкой.

Рабочий SQL:

Order.find_by_sql(
    "SELECT COUNT(order_number) AS order_count,
    restaurant_id, date_part('month', date) AS date_month,
    date_part('year', date) AS date_year 
    FROM orders
    WHERE restaurant_id is not null
    GROUP BY(restaurant_id, date_part('month', date), date_part('year', date))
    ORDER BY date_part('year', date) desc, date_part('month', date) desc;"
  )

Попытка 1 (не работает)

orders = Order.arel_table

Order
    .where.not(restaurant_id: nil)
    .select(:restaurant_id)
    .select(:date)
    .select(Order.arel_table[:order_number].count.as('order_count'))
    .select(
        Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), :date]),
        Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
    )
    .group(
        :restaurant_id, 
        Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]), 
        Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
    )

Попытка 2 (не работает)

orders = Order.arel_table
query = orders
      .where(orders[:restaurant_id].not_eq(nil))
      .project(
          orders[:restaurant_id],
          Order.arel_table[:order_number].count.as('order_count'),
          Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]).as('date_month'),
          Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]]).as('date_year'),
      )
      .group(
          orders[:restaurant_id],
          Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]),
          Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
      )
      .order(orders[:date].desc)
      .to_sql
Order.find_by_sql(query)

Оба подходаприведет к следующей ошибке:

PG :: GroupingError: ERROR: столбец "orders.date" должен появиться в предложении GROUP BY или использоваться в статистической функции

Проблема в том, что я не хочу группировать по дате, а по месяцам.Любые советы о том, как ее решить?

Я также первоначально попытался Arel::Nodes::NamedFunction.new('date_part', ['month', :date]) вместо Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]), но это привело к следующему:

Неподдерживаемый тип аргумента: String.Вместо этого постройте узел Ареля.

Любая помощь с благодарностью.Спасибо!

1 Ответ

0 голосов
/ 27 ноября 2018

Так что после нескольких часов копания получается большая ошибка!моей проблемой был набор default_scope на моей Order модели - вот где происходила сортировка по :date.В конце концов я решил удалить область по умолчанию, использовать сортировку там, где она действительно была нужна, и что мне осталось в отношении моего запроса, это:

orders = Order.arel_table
query = orders
  .where(orders[:restaurant_id].not_eq(nil))
  .project(
      orders[:restaurant_id],
      Order.arel_table[:order_number].count.as('order_count'),
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]).as('date_month'),
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]]).as('date_year'),
  )
  .group(
      orders[:restaurant_id],
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]),
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
  )
  .order(
      orders[:restaurant_id],
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), date]).desc,
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), date]).desc

  )
  .to_sql

Order.find_by_sql(query)

Извлеченный урок: избегать default_scope с, когда это возможно.Если вы работаете в одиночку, вы, вероятно, забудете, что использовали его со временем.Если вы работаете в команде, вам может потребоваться целый день, чтобы выдернуть волосы.

...