您的解决方案使用GROUP BY子句的扩展,允许按某些字段分组(在这种情况下,只是post_author):
GROUP BY wp_posts.post_author
并选择非聚合列:
SELECT wp_posts.*
不在group by子句中列出,或者不在聚合函数中使用(MIN、MAX、COUNT等)。
正确使用GROUP BY子句的扩展
当非聚合列的所有值对每一行都相等时,这很有用。
例如,假设你有一个表GardensFlowers(花园的名字,花园里生长的花):
INSERT INTO GardensFlowers VALUES
('Central Park', 'Magnolia'),
('Hyde Park', 'Tulip'),
('Gardens By The Bay', 'Peony'),
('Gardens By The Bay', 'Cherry Blossom');
你想要提取花园中生长的所有花,那里有很多花。然后你必须使用子查询,例如你可以使用这个:
SELECT GardensFlowers.*
FROM GardensFlowers
WHERE name IN (SELECT name
FROM GardensFlowers
GROUP BY name
HAVING COUNT(DISTINCT flower)>1);
如果你需要提取花园中唯一的花,你可以将HAVING条件更改为HAVING COUNT(DISTINCT flower)=1,但MySql也允许你这样做:
SELECT GardensFlowers.*
FROM GardensFlowers
GROUP BY name
HAVING COUNT(DISTINCT flower)=1;
没有子查询,不是标准SQL,但更简单。
GROUP BY子句扩展名使用不当
但是,如果SELECT每一行都不相等的非聚合列会发生什么?MySql为该列选择的值是什么?
看起来MySql总是选择它遇到的第一个值。
为了确保它遇到的第一个值恰好是您想要的值,您需要对有序查询应用GROUP BY,因此需要使用子查询。否则你不能这样做。
假设MySql总是选择它遇到的第一行,那么正确地对GROUP BY之前的行进行排序。但不幸的是,如果你仔细阅读文档,你会发现这个假设是不正确的。
当选择不总是相同的非聚合列时,MySql可以自由选择任何值,因此它实际显示的结果值是不确定的。
我发现这种获取非聚合列的第一个值的技巧被大量使用,而且它通常/几乎总是有效,我有时也使用它(自担风险)。但是由于没有记录,所以不能依赖这种行为。
这个链接(感谢ypercube!)GROUP BY技巧已经被优化,显示了相同查询在MySql和MariaDB之间返回不同结果的情况,可能是因为不同的优化引擎。
所以,如果这个把戏成功了,只是运气的问题。
另一个问题的公认答案在我看来是错误的:
HAVING wp_posts.post_date = MAX(wp_posts.post_date)
wp_posts。Post_date是一个未聚合的列,它的值没有正式确定,但它可能是遇到的第一个Post_date。但是由于GROUP BY技巧应用于无序表,因此无法确定遇到的第一个post_date是哪一个。
它可能会返回某个作者的唯一帖子,但这也不总是确定的。
一个可能的解决方案
我认为这是一个可能的解决方案:
SELECT wp_posts.*
FROM wp_posts
WHERE id IN (
SELECT max(id)
FROM wp_posts
WHERE (post_author, post_date) = (
SELECT post_author, max(post_date)
FROM wp_posts
WHERE wp_posts.post_status='publish'
AND wp_posts.post_type='post'
GROUP BY post_author
) AND wp_posts.post_status='publish'
AND wp_posts.post_type='post'
GROUP BY post_author
)
在内部查询中,我返回每个作者的最大发布日期。然后我考虑到同一个作者理论上可以同时有两个帖子,所以我只得到最大的ID。然后返回所有id值最大的行。使用连接而不是IN子句可以使它更快。
(如果您确定ID只增加,如果ID1 > ID2也意味着post_date1 > post_date2,那么查询可以变得更简单,但我不确定情况是否如此)。