2016-11-01 6 views
2

У меня есть проект Rails 4.2.5.x, работающий с PostGres. У меня есть таблица с аналогичной структурой этого:Как получить последние строки в группе

id, contact_id, date,  domain, f1, f2, f3, etc 
1, ABC,  01-01-16, abc.com, 1, 2, 3, ... 
2, ABC,  01-01-15, abc.com, 1, 2, 3, ... 
3, ABC,  01-01-14, abc.com, 1, 2, 3, ... 
4, DEF,  01-01-15, abc.com, 1, 2, 3, ... 
5, DEF,  01-01-14, abc.com, 1, 2, 3, ... 
6, GHI,  01-11-16, abc.com, 1, 2, 3, ... 
7, GHI,  01-01-16, abc.com, 1, 2, 3, ... 
8, GHI,  01-01-15, abc.com, 1, 2, 3, ... 
9, GHI,  01-01-14, abc.com, 1, 2, 3, ... 
... 
... 
99, ZZZ,  01-01-16, xyz.com, 1, 2, 3, ... 

Мне нужно запросить, чтобы найти:

  • Самые последние строки по date
  • отфильтрованные по домену
  • для отдельного contact_id (сгруппировано?)
  • ограниченный ряд результат. В этом примере я не добавляю это осложнение, но это нужно учитывать. Если существует 50 различных контактов, меня интересуют только три лучших по дате.
  • ID - это первичный ключ.
  • есть индексы на других колонках
  • столбцы fX указывают другие данные в модели, которая необходима (например, контактная электронная почта, например).

В MySQL, это было бы просто SELECT * FROM table WHERE domain='abc.com' GROUP BY contact_id ORDER BY date DESC, однако, Postgres жалуется, в этом случае, что:

ActiveRecord::StatementInvalid: PG::GroupingError: ERROR: column "table.id" must appear in the GROUP BY clause or be used in an aggregate function

Я ожидаю, чтобы получить обратно 3 ряда; 1, 4 и 6. В идеале я хотел бы вернуть полные строки в одном запросе ... но я согласен с тем, что мне может понадобиться сделать один запрос, чтобы сначала получить идентификаторы, а затем еще до find элементов, которые я хочу ,

Это ближайший я получил:

ExampleContacts 
    .select(:contact_id, 'max(date) AS max_date') 
    .where(domain: 'abc.com') 
    .group(:contact_id) 
    .order('max_date desc') 
    .limit(3) 

Однако ... это возвращает contact_id, не id. Я не могу добавить идентификатор строки.

EDIT:

По существу, мне нужно, чтобы получить первичный ключ обратно в строку, которая группируется на неосновной ключа и отсортированный по другому полю.

+0

DOH;) 4.2.5.x;) * мне редактирует * – Nick

ответ

1

Если вам нужны строки, вам не нужна группировка. Это просто Contact.select('DISTINCT ON (contact_id)').where(domain: 'abc.com').order(date: :desc).limit(3)

+0

Я просто наткнулся на то же самое ... Спасибо! – Nick

+1

Отлично! Рад, что он работает на вас. Не могли бы вы принять ответ? Благодарю. –

+0

Я опубликовал решение, которое я использовал на основе этого ответа: http://stackoverflow.com/a/40367494/224707 – Nick

0

Просто чтобы прояснить принятый ответ @ Murad-Юсуфов, я в конечном итоге делает это:

subquery = ExampleContacts.select('DISTINCT ON (contact_id) *') 
          .where(domain: 'abc.com') 
          .order(contact_id) 
          .order(date: :desc) 

ExampleContacts.from("(#{subquery.to_sql}) example_contacts") 
       .order(date: :desc) 
Смежные вопросы