这里有很多类似的问题,但我认为没有一个能充分回答这个问题。

如果可以的话,我将从当前最流行的问题继续,用他们的例子。

这个实例中的任务是获取数据库中每个作者的最新文章。

示例查询产生了不可用的结果,因为它并不总是返回的最新帖子。

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

目前公认的答案是

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

不幸的是,这个答案显然是错误的,在许多情况下产生的结果不如原始查询稳定。

我的最佳解决方案是使用表单的子查询

SELECT wp_posts.* FROM 
(
    SELECT * 
    FROM wp_posts
    ORDER BY wp_posts.post_date DESC
) AS wp_posts
WHERE wp_posts.post_status='publish'
AND wp_posts.post_type='post'
GROUP BY wp_posts.post_author 

我的问题很简单: 有没有办法在分组之前对行进行排序而不诉诸子查询?

编辑:这个问题是另一个问题的延续,我的具体情况略有不同。您可以(也应该)假设还有一个wp_posts。Id,是该特定帖子的唯一标识符。


当前回答

试试这个。只需要从每个作者那里获得最新发布日期的列表。这是它

SELECT wp_posts.* FROM wp_posts WHERE wp_posts.post_status='publish'
AND wp_posts.post_type='post' AND wp_posts.post_date IN(SELECT MAX(wp_posts.post_date) FROM wp_posts GROUP BY wp_posts.post_author) 

其他回答

您的解决方案使用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,那么查询可以变得更简单,但我不确定情况是否如此)。

**子查询在使用大型数据集时可能会对性能产生不良影响**

原始查询

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; 

修改查询

SELECT p.post_status,
       p.post_type,
       Max(p.post_date),
       p.post_author
FROM   wp_posts P
WHERE  p.post_status = "publish"
       AND p.post_type = "post"
GROUP  BY p.post_author
ORDER  BY p.post_date; 

因为我在选择子句中使用Max ==> Max (p.post_date),可以避免子选择查询和按组后的Max列排序。

只需使用max函数和group函数

    select max(taskhistory.id) as id from taskhistory
            group by taskhistory.taskid
            order by taskhistory.datum desc

以防万一是真的。我做过很多次这样的事情:

select * from 
  (select max(some_quantity) over (partition by id1, id2) as max_quantity, t.*
  from table_name t) tt 
where tt.max_quantity=tt.some_quantity;

这是具有字段some_quantity的条件最大值的分组。

试试这个。只需要从每个作者那里获得最新发布日期的列表。这是它

SELECT wp_posts.* FROM wp_posts WHERE wp_posts.post_status='publish'
AND wp_posts.post_type='post' AND wp_posts.post_date IN(SELECT MAX(wp_posts.post_date) FROM wp_posts GROUP BY wp_posts.post_author)