MySQL Order перед группировкой по - PullRequest
49 голосов
/ 28 февраля 2011

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

SELECT wp_posts.* FROM wp_posts
        WHERE wp_posts.post_status='publish'
        AND wp_posts.post_type='post'
        GROUP BY wp_posts.post_author           
        ORDER BY wp_posts.post_date DESC

Это правильно группирует выходные данные, поэтому я получаю только одно сообщение на автора, но это упорядочивает результаты после их группировки, а не до того, как они были выбраны.

Ответы [ 10 ]

22 голосов
/ 28 февраля 2011

select wp_posts.* from wp_posts
where wp_posts.post_status='publish'and wp_posts.post_type='post'
group by wp_posts.post_author
having wp_posts.post_date = MAX(wp_posts.post_date) /* ONLY THE LAST POST FOR EACH AUTHOR */
order by wp_posts.post_date desc


РЕДАКТИРОВАТЬ:

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

Компания, в которой я работаю, также использует Postgres и особенно SQL Server.Эти базы данных не позволяют такие запросы.Так что я знаю, что есть другой способ сделать это (я пишу решение ниже).Вам также необходимо знать, что вы делаете, если вы не группируете по всем столбцам, обработанным в проекции, или используете агрегатные функции.В противном случае пусть будет!

Я выбрал решение выше, потому что это конкретный вопрос.Том хочет получить последние сообщения для каждого автора на WordPress сайте.На мой взгляд, для анализа ничтожно, если автор делает больше, чем один пост в секунду.Wordpress должен даже запретить его, обнаружив двойной спам в спаме.По личному опыту я знаю, что при работе с такой грязной группой с MySQL есть действительно значительное преимущество в производительности.Но если вы знаете, что делаете, то можете это сделать!У меня есть такие грязные группы в приложениях, за которые я несу профессиональную ответственность.Здесь у меня есть таблицы с некоторыми строками mio, которые требуют 5-15 секунд вместо 100 ++ секунд.

Может быть полезно о некоторых плюсах и минусах: http://ftp.nchu.edu.tw/MySQL/tech-resources/articles/debunking-group-by-myths.html


SELECT
    wp_posts.*
FROM 
    wp_posts
    JOIN 
    (
        SELECT
            g.post_author
            MAX(g.post_date) AS post_date
        FROM wp_posts as g
        WHERE
            g.post_status='publish'
            AND g.post_type='post'
        GROUP BY g.post_author
    ) as t 
    ON wp_posts.post_author = t.post_author AND wp_posts.post_date = t.post_date

ORDER BY wp_posts.post_date

Но если для автора здесь более одного поста в секунду, вы получите более одного, а не единственного последнего .

Теперь вы можете снова вращать колесо и получить пост с самым высоким Id.Даже здесь, по крайней мере, не гарантируется, что вы действительно получите последний.

14 голосов
/ 28 февраля 2011

Не уверен, правильно ли я понимаю ваше требование, но следующее внутреннее утверждение получает список последних post_date для каждого автора и объединяет их с таблицей wp_posts, чтобы получить полную запись.

SELECT  *
FROM    wp_posts wp
        INNER JOIN (
          SELECT  post_author
                  , MAX(post_date) AS post_date
          FROM    wp_posts
          WHERE   post_status = 'publish'
                  AND post_type = 'post'
          GROUP BY
                  post.author
        ) wpmax ON wpmax.post_author = wp.post_author
                   AND wpmax.post_date = wp.post_date
ORDER BY
        wp.post_date DESC
12 голосов
/ 10 мая 2012

Я думаю, что ответ @edze неправильный.

В руководстве MySQL вы можете прочитать:

MySQL расширяет использование GROUP BY, так чтосписок выбора может ссылаться на неагрегированные столбцы, не указанные в предложении GROUP BY.Вы можете использовать эту функцию для повышения производительности, избегая ненужной сортировки и группировки столбцов.Однако это полезно, прежде всего, когда все значения в каждом неагрегированном столбце, не названном в GROUP BY, одинаковы для каждой группы.Сервер может выбрать любое значение из каждой группы, поэтому, если они не совпадают, выбранные значения являются неопределенными.Кроме того, на выбор значений из каждой группы нельзя повлиять, добавив предложение ORDER BY.Сортировка набора результатов происходит после выбора значений, и ORDER BY не влияет на то, какие значения выбирает сервер.

Две замечательные ссылки:

Извините, но я не могу комментировать ответ @edze из-за своей репутации, поэтому я написал новый ответ.

6 голосов
/ 30 апреля 2013

Выполните GROUP BY после ORDER BY, поместив запрос в GROUP BY следующим образом:

SELECT t.* FROM (SELECT * FROM table ORDER BY time DESC) t GROUP BY t.author
5 голосов
/ 28 февраля 2011

не имеет значения, если вы заказываете до или после группового оператора, потому что порядок означает только, что 213 идет к 123 или 321 и не более.group by принимает только НЕКОТОРЫЕ записи в столбце, а не только последние.Я считаю, что вы работаете с подвыборками здесь, как

SELECT wp_posts.* FROM wp_posts
        WHERE wp_posts.post_status='publish'
        AND wp_posts.post_type='post'
        AND wp_posts.post_date = (Select max(post_date) from wp_posts where author = ... )
4 голосов
/ 05 мая 2011

Что вы думаете об этом ?? Кажется, работает на меня

SELECT wp_posts.post_author, MAX(wp_posts.post_date), wp_posts.status, wp_posts.post_type
FROM wp_posts
    WHERE wp_posts.post_status='publish'
    AND wp_posts.post_type='post'
    GROUP BY wp_posts.post_author

Это приносит мне всех Авторов с самой последней датой post_date ... Вы идентифицируете проблему там ?? Я не

1 голос
/ 24 апреля 2013
    SELECT wp_posts.*,max(wp_posts.post_date) FROM wp_posts
    WHERE wp_posts.post_status='publish'
    AND wp_posts.post_type='post'
    GROUP BY wp_posts.post_author 
0 голосов
/ 27 декабря 2014

ЗДЕСЬ простой ответ от http://www.cafewebmaster.com/mysql-order-sort-group

SELECT * FROM 
(
select * from `my_table` order by timestamp desc
) as my_table_tmp

GROUP BY catid
ORDER BY nid desc

для меня это творит чудеса

0 голосов
/ 25 апреля 2014

Используйте код ниже ...

<?php
//get all users, iterate through users, query for one post for the user,
//if there is a post then display the post title, author, content info
$blogusers = get_users_of_blog();
if ($blogusers) {
  foreach ($blogusers as $bloguser) {
    $args = array(
    'author' => $bloguser->user_id,
      'showposts' => 1,
      'caller_get_posts' => 1
    );
    $my_query = new WP_Query($args);
    if( $my_query->have_posts() ) {
      // $user = get_userdata($bloguser->user_id);
      // echo 'This is one post for author with User ID: ' . $user->ID . ' ' . $user-    >user_firstname . ' ' . $user->user_lastname;
      while ($my_query->have_posts()) : $my_query->the_post(); ?>
        <a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?    php the_title_attribute(); ?>"><?php the_title(); ?></a>

        <small><?php the_time('F jS, Y') ?> by <?php the_author_posts_link() ?>     </small><?php
        the_content();
      endwhile;
    }
  }
}
?>
0 голосов
/ 27 февраля 2012

Когда наша таблица стала большой, нужно проверить и производительность.Я проверил все варианты в вопросах здесь, с системой PM с сообщениями 136K и таблицей ссылок с 83K строками.

Когда вам нужно только считать или только идентификаторы - решение Алекса является лучшим.

SELECT wp_posts.post_author, MAX(wp_posts.post_date), wp_posts.status, wp_posts.post_type
FROM wp_posts
    WHERE wp_posts.post_status='publish'
    AND wp_posts.post_type='post'
    GROUP BY wp_posts.post_author

Когда вам нужны другие поля, мне нужно изменить решение Husky110 (для моей таблицы - здесь это только пример - не проверено), чтобы в моих таблицах в 10 раз быстрее, чем опция подзапроса:

SELECT wp_posts.* FROM wp_posts,
    (Select post_id as pid,  max(post_date) maxdate from wp_posts where author = ... group by author order by maxdate  desc limit 4) t
    WHERE wp_posts.post_status='publish'
    AND wp_posts.post_type='post'
    AND wp_posts.post_id = pid

Это изменение может выбрать более одной публикации (например, одну для пользователя) и может быть изменено для других решений.

Моше.

...