Преобразование запроса SQL в запрос Rails AREL?

У меня есть рабочий SQL-запрос благодаря помощи Эрвина Брандштеттера в моем предыдущем вопросе 'Заказ с отношением has_many'.

Как мне превратить этот SQL в запрос ActiveRecords или AREL для использования в области видимости?

SELECT a.*
FROM   articles a
LEFT   JOIN (
   SELECT DISTINCT ON (article_id)
          article_id, value
   FROM   metrics m
   WHERE  name = 'score'
   ORDER  BY article_id, date_created DESC
   ) m ON m.article_id = a.id
ORDER  BY m.value DESC;

Ближе всего я пришел с помощью друзей ...

scope :highest_score, select("articles.*").joins("LEFT JOIN (SELECT 
      DISTINCT ON (article_id) article_id, value FROM metrics WHERE name = 
      'score' ORDER  BY article_id, date_created DESC) ON metrics.article_id = 
      articles.id").order("metrics.value DESC")

... что дает мне ошибку:

ActiveRecord::StatementInvalid: PGError:
      ERROR:  subquery in FROM must have an alias

ОБНОВЛЕНИЕ:

В моем предыдущем вопросе есть полное описание соответствующей схемы и запроса. Но в основном Articles have_many Metrics, а Metric имеет name и value. Мой запрос упорядочивает Articles по наибольшему value из последних Metric с name = 'score'.

Спасибо!

РЕШЕНИЕ:

Спасибо Маттерику за то, что указал мне правильное направление! Его запрос работает на SQLite, но из-за (соответствующей) нетерпимости postgresql к двусмысленности окончательная рабочая область:

scope :highest_score, joins(:metrics).where("metrics.name" => "score")
      .order("metrics.value desc").group("metrics.article_id", 
      "articles.id", "metrics.value", "metrics.date_created")
      .order("metrics.date_created desc")

Вопрос SO, на который Материк ссылался в своих комментариях, объясняет проблему здесь — и почему sqlite виноват в принятии неоднозначных запросов, а postgresql — в отказе. Для меня это хороший пример преимущества использования той же базы данных для локальной разработки, что и для производства.


person djoll    schedule 07.05.2013    source источник
comment
как выглядит ваша схема и ассоциации? с этой информацией легче попробовать ваш запрос;). без дополнительной информации, возможно, это работает: scope :highest_score, lambda { Article.all.includes(:metrics).where(:name =› score).order(article_id desc и date_created desc) }   -  person Matthias    schedule 07.05.2013
comment
Спасибо, Материк! Я не хотел дважды публиковать информацию, так как моя схема и ассоциации описаны в этом первом вопросе: stackoverflow.com/questions/16382606/ — но в основном статьи has_many Metrics, а Metric имеет имя и значение. Мой запрос упорядочивает статьи по наивысшему значению самой последней метрики с именем = «оценка». Спасибо за любую помощь, которую вы можете дать! диджей   -  person djoll    schedule 07.05.2013


Ответы (1)


я думаю это должно сработать

class Article < ActiveRecord::Base

  scope :highest_score, lambda { Article.joins(:metrics).where("metrics.name" => "score").order("metrics.value").group(:article_id).order("metrics.article_id desc").order("metrics.date_created desc") }

end
person Matthias    schedule 07.05.2013
comment
Спасибо, Меттерик. К сожалению, я получаю эту ошибку: ActiveRecord::StatementInvalid: PGError: ERROR: столбец metrics.score не существует. LINE 1: ...P BY article_id ORDER BY metrics.article_id desc, metrics.sc... хотя я думаю, что ваш запрос упускает несколько частей, а именно упорядочение статей по Metric.value для Metric.name = score. Спасибо, что посмотрели! - person djoll; 07.05.2013
comment
Обновил мой ответ, но я больше не уверен :). Я не получаю ActiveRecord::StatementInvalid: PGError: ERROR. Я просто попробовал это с sqlite3 на моей локальной машине. - person Matthias; 07.05.2013
comment
Как я вижу, вы получаете PostgressError, возможно, этот вопрос может помочь вам stackoverflow.com/questions/16418504/pgerror-in-group-by-clause - person Matthias; 07.05.2013
comment
Спасибо Матхерик. Эта ссылка помогает объяснить проблему и привести меня к решению, используя ваш запрос. Спасибо еще раз! ANS: scope :highest_score, lambda { Article.joins(:metrics).where(metrics.name =› score).order(metrics.value desc).group(metrics.article_id, article.id, metrics.value, metrics. date_created).order(metrics.date_created описание) } - person djoll; 08.05.2013
comment
Кроме того, лямбда не нужна (думаю, нужна только для динамических областей, где вы передаете переменную), поэтому я удалил ее. - person djoll; 08.05.2013
comment
Да, я думаю, что лямбда не нужна в рельсах 3.2, но в рельсах 4 вы получите предупреждение об устаревании или сразу ошибку, если я не ошибаюсь. - person Matthias; 08.05.2013