2011-02-28 30 views
46

我需要为每位作者查找最新帖子,然后对结果进行分组,以便每位作者只发布一条最新帖子。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 

这是正确的分组输出,所以我只能得到每一个作家后,但对结果进行排序,他们已经分组并没有被选中之前,他们之后。

+4

做,这是一个内部查询 ['code'] (SELECT wp_posts的最快方法。* FROM(SELECT * FROM wp_posts ORDER BY wp_post.post_date DESC)as wp_posts WHERE wp_posts.post_status ='publish' AND wp_posts.pos t_type ='post' GROUP BY wp_posts.post_author;) 也许它不是最有效的,但它的工作原理。 – Milos 2011-08-19 12:35:44

+1

我不认为这个问题的接受答案是正确的,并继续在这里的问题http://stackoverflow.com/questions/14770671/mysql-order-by-before-group-by – 2013-02-08 11:05:44

+0

@RobForrest嘿,我很高兴地更新选定的答案:)几年前我问过这个,所以如果有更好的方法,我很乐意将人们指向它 – Tom 2013-02-08 11:42:57

回答

22

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做一个如此肮脏的团体在性能方面会有非常显着的好处。但是如果你知道你做了什么,那么你可以做到!我在专业上负责的应用中有这样的肮脏组。在这里我有一些需要5-15秒而不是100 ++秒的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 

但是,如果这里是每秒一个以上职位的作家,你会得到更多然后一排,而不是只最后一个

现在,您可以再次旋转轮子并获得最高的帖子Id。即使在这里,至少不能保证你真的会得到最后一个。

+1

它只是我,或在HAVING子句中使用MAX()不起作用?我试了一下,得到了'聚合函数的无效使用'错误。我究竟做错了什么? – Sophivorus 2012-03-15 05:38:11

+7

这不只是你;我不认为这个答案是有道理的。我没有遇到任何错误,但是它只给出了一行,这是整个集合中最高的一行,而不是每个组 - 这是有道理的,因为HAVING和ORDER一样,在行集已经建立之后就被处理了。 – LinusR 2012-04-23 18:10:29

+1

MySQL只返回一行。其他DBMS实施更严格的SQL标准。如果想获得真正严格的聚合,则必须对投影中处理的所有列进行分组或使用聚合函数。 – edze 2012-04-23 20:30:16

5

如果您在组语句之前或之后进行订购,则无关紧要,因为订单仅意味着213进入123或321而不是更多。通过每列只有一些入口,不仅是最新的。我认为你与子查询在这里工作就像

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

它帮助了我!谢谢!! – rAjA 2013-09-12 07:48:25

14

不知道如果我理解你的要求,正确的,但以下内部语句获取最新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 
+0

这对我有用,但只有在我在INNER JOIN中向SELECT中添加了一个'ORDER BY'后(在此之前,它不一定返回每个作者的最新帖子)。 – ACJ 2012-10-10 08:28:18

4

您对此有何看法?似乎为我工作

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 ...你确定一个问题吗?我不

+2

这可能不一定会带回最近的帖子。 – 2012-08-08 14:38:03

+1

它不能解决问题 – helpse 2015-05-07 22:10:20

0

当我们的表变大,性能需要检查也。 我检查了这里所有问题的选项,其中带有136K消息的PM系统和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溶液(以我的表的设计 - 这是唯一的例子 - 不选中),在我的表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 

此更改可以选择多个帖子(例如一个用户),并可以修改为其他解决方案。

Moshe。

12

我认为@edze的回应是错误的。

MySQL manual你可以阅读:

MySQL的扩展使用GROUP BY的,这样的选择列表可参考 在GROUP BY子句中未命名的非聚合列。您可以使用 此功能通过避免不必要的列 排序和分组来获得更好的性能。但是,这主要适用于未在GROUP BY中命名的每个非聚合列中的所有 值都是 ,而且每个组都相同。服务器可以自由选择每个 组中的任何值,因此除非它们相同,否则所选值为 不确定。此外,每个组 的值的选择都不会受到添加ORDER BY子句的影响。 结果集的排序在选择值后发生,而ORDER BY确实不会影响服务器选择的值。

两个伟大的引用:

很抱歉,但我不能评论的@edze响应,因为我的名气,所以我写了一个新的答案。

+1

@Lieven响应是正确的。但是,如果来自同一作者的两篇文章得到相同的日期,则需要最终的GROUP BY。 – aanton 2012-05-10 06:55:28

+0

第二个链接真的有助于理解。 – 2016-09-30 07:19:58

1
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 
+3

你好!请确保为您的帖子添加解释;只有一个代码块作为答案通常不会帮助提问者明白为什么答案是正确的(当然,这个问题在两年前已经提出并回答了,所以我相信Tom已经有了他的答案!) – 2013-04-24 19:28:27

6

做一组由ORDER BY后,通过包装与GROUP BY查询是这样的:

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

非常低效,并且可以很容易地被MySQL优化器 – newtover 2013-04-30 20:21:05

+1

重写出来。我解决了这个问题,因为它确实工作并且运行速度足够快(在我的数据库上少于2秒)。 @newtover我想找到更高效的解决方案,但我尝试了许多其他建议,但我无法让它们中的任何一个返回我所需要的(因为我有更复杂的SELECT和WHERE子句)。我可以将我的复杂查询并将其粘贴到“MySQL优化器”中以解决它吗?这将如何工作? – 11101101b 2013-05-01 19:22:20

+0

对不起,我错过了你的评论。实际上,我在[http://stackoverflow.com/questions/1313120/retrieving-the-last-record-in-each-group/8757062#8757062]中描述的方法非常高效,但需要很好地理解它是如何工作的。如果您对需要优化的特定查询有疑问,我可以提供具体答案。你的方法效率低下,因为你实际上把所有东西都放在一个没有索引的临时表中,然后用一个特定于MySQL的黑客进行顺序读取。最好不要使用黑客或将其用于有效的解决方案。 – newtover 2013-05-06 19:09:57

0

使用下面的代码...

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

谢谢,我专门寻找SQL,而不是PHP。这个问题已经有了很好的答案。有大量未答复的PHP问题http://stackoverflow.com/questions/tagged/php?sort=unnswered – Tom 2014-04-25 15:17:26