web-dev-qa-db-ja.com

グループ化前のMySQL注文

各著者の最新の投稿を見つけて、結果をグループ化する必要があるため、各著者の最新の投稿は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           
        ORDER BY wp_posts.post_date DESC

これにより、出力が正しくグループ化されるため、著者ごとに投稿が1つだけになりますが、結果は、グループ化された後ではなく、選択される前に結果が並べ替えられます。

49
Tom

_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サイトで各著者の最近の投稿を取得したいと考えています。著者が1秒間に複数の投稿を行う場合、分析は無視できます。Wordpressは、スパムの二重投稿の検出によってそれを禁止する必要があります。MySQLを使用してこのような汚いグループを実行すると、パフォーマンスに非常に大きなメリットがあることを個人的な経験から知っています。私はプロに責任があるアプリにそのような汚いグループがありますここでは、100 ++秒ではなく5-15秒を必要とするmio行のあるテーブルがあります。

いくつかの長所と短所について役に立つかもしれません: 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
_

しかし、ここに著者の投稿が1秒あたり1つ以上ある場合、最後の1つだけでなく、1行より多くなります。

これで、ホイールを再び回転させて、Idが最高の投稿を取得できます。ここでさえ、少なくとも最後のものを取得することは保証されません。

22
edze

要件が正しいかどうかはわかりませんが、次の内部ステートメントは各著者の最新の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
14

@edzeの応答は間違っていると思います。

MySQLマニュアル で読むことができます:

MySQLはGROUP BYの使用を拡張して、選択リストがGROUP BY句で指定されていない非集計列を参照できるようにします。この機能を使用して、不必要な列のソートとグループ化を回避することにより、パフォーマンスを向上させることができます。ただし、これは主に、GROUP BYで名前が付けられていない各非集計列のすべての値が各グループで同じ場合に役立ちます。サーバーは各グループから任意の値を自由に選択できるため、それらが同じでない限り、選択される値は不定です。さらに、各グループからの値の選択は、ORDER BY句を追加しても影響を受けません。結果セットのソートは値が選択された後に行われ、ORDER BYはサーバーが選択する値には影響しません。

2つの優れたリファレンス:

申し訳ありませんが、評判のために@edze応答にコメントすることはできませんので、新しい回答を書きました。

12
aanton

次のようにクエリをGROUP BYでラップすることにより、ORDER BYの後にGROUP BYを実行します。

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

順序は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 = ... )
5
Husky110

これについてどう思う??私のために働くようです

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が最も更新されたすべての著者が表示されます...そこで問題を特定していますか??しません

4
Alex
    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 
1
Mhd Jazaery

テーブルが大きくなったとき、パフォーマンスもチェックする必要があります。ここで質問のすべてのオプションをチェックしました。PMシステムは136Kメッセージ、リンクテーブルは83K行です。

カウントのみ、またはIDのみが必要な場合-アレックスのソリューションが最適です。

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

この変更により、複数の投稿(たとえば、ユーザー用の投稿)を選択でき、他のソリューションに変更できます。

モシェ。

0
Moshe L

以下のコードを使用してください...

<?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
Kausha Mehta

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
Black Bronco