Как я могу получить самую новую запись в каждой группе в результатах поиска DBIx :: Class? - PullRequest
4 голосов
/ 22 августа 2011

Я использую group_by в DBIx :: Class результатах поиска.Результатом, возвращаемым для каждой группы, всегда является строка в группе с самым низким идентификатором (т.е. самая старая строка в группе).Вместо этого я ищу способ получить строку с самым высоким идентификатором (то есть самой новой строкой в ​​группе).

Проблема в основном такая же: Получение последней записи в каждомgroup ... за исключением того, что я использую DBIx :: Class, а не raw SQL.

Чтобы поставить вопрос в контексте:

У меня есть таблица музыкальных обзоров

review
------
id
artist_id
album_id
pub_date
...other_columns...

Может быть несколько обзоров для любого данного artist_id / album_id.Я хочу получить самые последние обзоры в порядке убывания даты, не более одного отзыва на artist_id / album_id.

Я пытался сделать это, используя:

$schema->resultset('Review')->search(
  undef,
  {
    group_by => [ qw/ artist_id album_id / ],
    order_by => { -desc => 'pub_date' },
  }
);

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

1 Ответ

2 голосов
/ 22 августа 2011

Чтобы это работало, вы полагаетесь на некорректное поведение базы данных.Вы не сможете выбирать столбцы из таблицы, когда используете group by , если только они не используют агрегатную функцию (min, max и т. Д.) Или не указаны в предложении group by.

В MySQL даже руководство признает, что это неправильно - хотя оно и поддерживает это.

Я думаю, что вам нужно сделать, это получить последние даты обзоров с max (pub_date):

my $dates = $schema->resultset('Review')->search({},
  {
    select   => ['artist_id', 'album_id', {max => 'pub_date'}],
    as       => [ qw(artist_id album_id recent_pub_date) ],
    group_by => [ qw(artist_id album_id) ],
  }
);

Затем перейдите к циклу, чтобы получить обзор:

while (my $review_date = $dates->next) {
    my $review = $schema->resultset('Review')->search({
        artist_id => $review_date->artist_id,
        album_id  => $review_date->album_id,
        pub_date  => $review_date->get_column('recent_pub_date'),
    })->first;
}

Да - это больше запросов, но имеет смысл - что, если два отзыва находятся в одну и ту же дату - как БДзнаете, какой из них вернуть в операторе выбора?

...