MySQL排序依据在分组依据之前
这里有很多类似的问题,但我认为没有人能充分回答这个问题 我将继续从当前最流行的,并使用他们的例子,如果这是好的 本例中的任务是获取数据库中每个作者的最新文章 示例查询产生不可用的结果,因为它并不总是返回的最新帖子MySQL排序依据在分组依据之前,mysql,group-by,sql-order-by,Mysql,Group By,Sql Order By,这里有很多类似的问题,但我认为没有人能充分回答这个问题 我将继续从当前最流行的,并使用他们的例子,如果这是好的 本例中的任务是获取数据库中每个作者的最新文章 示例查询产生不可用的结果,因为它并不总是返回的最新帖子 SELECT wp_posts.* FROM wp_posts WHERE wp_posts.post_status='publish' AND wp_posts.post_type='post' GROUP BY wp_posts.post_author
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
我的问题很简单:
在分组之前,是否仍然可以不借助子查询对行进行排序?
编辑:这个问题是另一个问题的延续,我的具体情况略有不同。您可以(也应该)假设还有一个wp_posts.id,它是该特定帖子的唯一标识符。首先,不要在select中使用*,会影响它们的性能并妨碍使用group by和order by。 请尝试以下查询:
SELECT wp_posts.post_author, wp_posts.post_date as pdate FROM wp_posts
WHERE wp_posts.post_status='publish'
AND wp_posts.post_type='post'
GROUP BY wp_posts.post_author
ORDER BY pdate DESC
如果不按ORDER BY指定表,而只指定别名,则它们将对select的结果进行排序。否。在分组之前对记录进行排序是没有意义的,因为分组将改变结果集。子查询方式是首选方式。如果速度太慢,您必须更改表设计,例如,将每个作者最后一篇文章的id存储在一个单独的表中,或者引入一个布尔列,指示每个作者的最后一篇文章。在子查询中使用
ORDER by
不是解决此问题的最佳方法
按作者获取max(post\u-date)
的最佳解决方案是使用子查询返回max-date,然后在post\u-author
和max-date上将其连接到表中
解决办法应该是:
SELECT p1.*
FROM wp_posts p1
INNER JOIN
(
SELECT max(post_date) MaxPostDate, post_author
FROM wp_posts
WHERE post_status='publish'
AND post_type='post'
GROUP BY post_author
) p2
ON p1.post_author = p2.post_author
AND p1.post_date = p2.MaxPostDate
WHERE p1.post_status='publish'
AND p1.post_type='post'
order by p1.post_date desc
如果您有以下示例数据:
CREATE TABLE wp_posts
(`id` int, `title` varchar(6), `post_date` datetime, `post_author` varchar(3))
;
INSERT INTO wp_posts
(`id`, `title`, `post_date`, `post_author`)
VALUES
(1, 'Title1', '2013-01-01 00:00:00', 'Jim'),
(2, 'Title2', '2013-02-01 00:00:00', 'Jim')
;
子查询将返回以下内容的最长日期和作者:
MaxPostDate | Author
2/1/2013 | Jim
然后,由于您要将其连接回表中,因此在这两个值上,您将返回该帖子的完整详细信息
看
展开我关于使用子查询准确返回此数据的评论
MySQL不会强制您按列表中包含的每一列对进行分组。因此,如果您仅按一列进行分组,但总共返回10列,则不能保证属于返回的post_作者的其他列值。如果列不在groupby
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
将子查询与聚合函数一起使用将确保每次返回正确的作者和帖子
顺便说一句,MySQL允许您在子查询中使用ORDER BY
,并允许您将GROUP BY
应用于SELECT
列表中的并非每一列,但在包括SQL Server在内的其他数据库中不允许此行为。尝试此操作只需从每位作者那里获取最新发布日期的列表。就这样
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)
您的解决方案使用了一个允许按某些字段分组的子句(在本例中,只需post\u author
):
并选择非聚集列:
SELECT wp_posts.*
未在group by子句中列出的,或未在聚合函数中使用的(最小值、最大值、计数等)
正确使用GROUP BY子句的扩展名
当非聚合列的所有值对于每一行都相等时,这非常有用
例如,假设您有一个表GardensFlowers
(name
花园,flower
生长在花园中):
你想把花园里所有的花都提取出来,在那里有很多花。然后您必须使用子查询,例如,您可以使用:
SELECT GardensFlowers.*
FROM GardensFlowers
WHERE name IN (SELECT name
FROM GardensFlowers
GROUP BY name
HAVING COUNT(DISTINCT flower)>1);
SELECT GardensFlowers.*
FROM GardensFlowers
GROUP BY name
HAVING COUNT(DISTINCT flower)=1;
如果您需要提取花园中唯一的花,您可以将HAVING条件更改为HAVING COUNT(DISTINCT flower)=1,但MySql也允许您使用此选项:
SELECT GardensFlowers.*
FROM GardensFlowers
WHERE name IN (SELECT name
FROM GardensFlowers
GROUP BY name
HAVING COUNT(DISTINCT flower)>1);
SELECT GardensFlowers.*
FROM GardensFlowers
GROUP BY name
HAVING COUNT(DISTINCT flower)=1;
没有子查询,不是标准SQL,但更简单
对GROUP BY子句的扩展使用不正确
但是,如果选择每行不相等的非聚合列,会发生什么情况?MySql为该列选择的值是什么
看起来MySql总是首先选择它遇到的值
为了确保它遇到的第一个值正是您想要的值,您需要将groupby
应用于有序查询,因此需要使用子查询。否则你做不到
假设MySql总是选择它遇到的第一行,那么您将正确地在GROUP BY之前对行进行排序。但不幸的是,如果您仔细阅读文档,您会发现这个假设是不正确的
当选择不总是相同的非聚合列时,MySql可以自由选择任何值,因此它实际显示的结果值是不确定的
我发现这种获取非聚合列的第一个值的技巧被大量使用,而且通常/几乎总是有效的,有时我也会使用它(风险由我自己承担)。但由于没有记录,你不能依赖这种行为
这个链接(感谢ypercube!)显示了一种情况,同一个查询在MySql和MariaDB之间返回不同的结果,可能是因为不同的优化引擎
所以,如果这个把戏奏效,那只是运气的问题
在我看来,这是个错误:
HAVING wp_posts.post_date = MAX(wp_posts.post_date)
wp\u posts。post\u date
是一个非聚合列,其值将不确定,但可能是遇到的第一个post\u date
。但由于GROUP BY技巧应用于无序表,因此无法确定遇到的第一个post_日期
它可能返回的帖子是单个用户的唯一帖子
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
)
SELECT x.*
FROM my_table x
JOIN (SELECT grouping_criteria,MAX(ranking_criterion) max_n FROM my_table GROUP BY grouping_criteria) y
ON y.grouping_criteria = x.grouping_criteria
AND y.max_n = x.ranking_criterion;
SELECT x.*
FROM my_table x
LEFT
JOIN my_table y
ON y.joining_criteria = x.joining_criteria
AND y.ranking_criteria < x.ranking_criteria
WHERE y.some_non_null_column IS NULL;
...
WHERE wp_posts.post_status='publish' AND wp_posts.post_type='post'
GROUP BY wp_posts.post_author 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 DESC
ORDER BY wp_posts.post_date DESC;
SELECT *
FROM wp_posts
INNER JOIN
(
SELECT max(post_date) post_date, post_author
FROM wp_posts
WHERE post_status='publish' AND post_type='post'
GROUP BY post_author
ORDER BY post_date DESC
-- LIMIT GOES HERE
) p2 USING (post_author, post_date)
WHERE post_status='publish' AND post_type='post';
SELECT *
FROM (
SELECT post_id
FROM wp_posts
WHERE post_status='publish' AND post_type='post'
GROUP BY post_author DESC
ORDER BY post_date DESC
-- LIMIT GOES HERE
) as ids
JOIN wp_posts USING (post_id);
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;
select max(taskhistory.id) as id from taskhistory
group by taskhistory.taskid
order by taskhistory.datum desc