Заказ MySQL перед Группой

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

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

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

Ответ 1

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дел >


EDIT:

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

В компании, в которой я работаю, также используются 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. Даже здесь, по крайней мере, не гарантировано, что вы действительно получите последний.

Ответ 2

Не уверен, что я правильно понимаю ваше требование, но после внутреннего оператора получает список последнего 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

Ответ 3

Я думаю, что ответ @edze неверен.

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

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

Две отличные ссылки:

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

Ответ 4

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

SELECT t.* FROM (SELECT * FROM table ORDER BY time DESC) t GROUP BY t.author

Ответ 5

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

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 = ... )

Ответ 6

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

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... Вы идентифицируете проблему там? Я не

Ответ 7

    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 

Ответ 8

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

Когда вам нужно только подсчитать или использовать только ID - решение Alex лучше всего.

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 (для моей таблицы - здесь это только пример - не проверено), что в моих таблицах 10x быстрее, чем опция подзапроса:

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

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

Моше.

Ответ 9

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

<?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;
    }
  }
}
?>

Ответ 10

ЗДЕСЬ простой ответ от 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

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