MySQL Order перед группировкой по

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

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 ответов

Решение

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

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

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

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

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

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

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

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

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

Не имеет значения, если вы заказываете до или после группового оператора, потому что порядок означает только, что 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 = ... )

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

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

    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 

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

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

Когда наша таблица стала большой, нужно проверить и производительность. Я проверил все варианты в вопросах здесь, с системой 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

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

Моше.

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

<?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;
    }
  }
}
?>
Другие вопросы по тегам