MySQL group by和max返回错误的行

时间:2011-11-28 21:20:18

标签: mysql group-by greatest-n-per-group

我有两张桌子,我试着找到每天得分最高的“帖子”。

CREATE TABLE IF NOT EXISTS `posts_points` (
  `post_id` int(10) unsigned NOT NULL,
  `comments` smallint(5) unsigned NOT NULL,
  `likes` smallint(5) unsigned NOT NULL,
  `favorites` smallint(5) unsigned NOT NULL,
   PRIMARY KEY (`post_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `posts` (
  `profile_id` int(10) unsigned NOT NULL,
  `post_id` int(10) unsigned NOT NULL,
  `pubdate_utc` datetime NOT NULL,
  PRIMARY KEY (`post_id`),
  KEY `profile_id` (`profile_id`),
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

我已经尝试过以下查询。它返回正确的分数,但其他列只是随机行。我做错了什么?

SELECT p.post_id, p.profile_id
   , MAX(t1.score)
   , DATE_FORMAT(t1.pubdate_utc, '%d %b') post_date
   , DATE(t1.pubdate_utc) mydate
FROM
(
   SELECT p.profile_id, p.post_id, p.pubdate_utc
      , (pp.comments + pp.likes + pp.favorites) AS score
   FROM posts p 
   INNER JOIN posts_points pp ON p.post_id = pp.post_id
) t1
INNER JOIN posts p ON t1.post_id = p.post_id
   AND t1.pubdate_utc = p.pubdate_utc
GROUP BY mydate
ORDER BY mydate DESC
LIMIT 18;

5 个答案:

答案 0 :(得分:2)

我一直遇到这个问题。当MySQL运行聚合函数时,对于任何非聚合列,它只是拉出它为该组运行的第一个数据,无论它是否来自MAX行。因此,您需要做的是在内部查询中对数据进行排序,使得maxes在其组中是第一位的。看看这是否适合你:

SELECT t.post_id,
       t.profile_id,
       t.score,
       t.pubdate_utc
FROM (SELECT p.profile_id,
             p.post_id,
             p.pubdate_utc,
             (pp.comments + pp.likes + pp.favorites) score
      FROM posts p
      JOIN posts_points pp ON p.post_id = pp.post_id
      WHERE p.pubdate_utc >= DATE_ADD(DATE(NOW()), INTERVAL -17 DAY)
      ORDER BY score DESC
     ) t
GROUP BY DATE(t.pubdate_utc) DESC
;

请注意,我这里没有使用MAX功能。按分数降序排序,然后在外部查询中按日期分组将按日期提取最高分。另请注意,我将WHERE子句放在内部查询中。像这样的内部查询(有时是必要的)不是非常有效,因为它们没有外部查询的优化索引,所以要确保你的内部结果集尽可能小。最后,请注意GROUP BY DATE(t.pubdate_utc)。如果我没有将其减少到仅仅是日期信息,那么将会有超过18个结果,因为时间也被计算在内。

修改:更改为INTERVAL -17 DAY,最多可提供18个结果,而非19个。

答案 1 :(得分:0)

Column1  Column2
C        d
A        any thing
D        y
B        z  

如果您按Column1订购此数据,那么它看起来就像这样.....只需订购第一列....

Column1  Column2
A        any thing
B        z            
C        d
D        y

答案 2 :(得分:0)

了解你想做什么有点棘手。

单词(列(帖子,评论,收藏夹)和PK),我知道您更新的值会增加,并且不会记录每次投票。

此选择返回帖子中的数据和分数,通过排序更大的点,限制为18。

        SELECT P.post_id,
               P.profile_id,
               (PP.comments + PP.likes + PP.favorites) AS score,
               DATE_FORMAT (P.pubdate_utc, '%d %b') AS post_data,
               DATE (P.pubdate_utc) AS mydate
          FROM posts P
    INNER JOIN posts_points PP
            ON (= P.post_id PP.post_id)
      ORDER BY 3 DESC
         LIMIT 18;

如果您想要选择当天最多的选票,您必须记录不同的赞/赞,需要该表中的数据(posts_points)。

答案 3 :(得分:0)

哇!棘手。例如,总是存在最大关系的可能性

下面的解决方案创建了一天的max_scores的中间列表,然后获取其分数等于当天最大值的所有帖子。它返回联系,因此您可以在给定的一天获得两行。我请求你原谅我无法测试,所以给予反馈,我相信我们可以做到这一点来做你需要的。

SELECT p.profile_id, p.post_id, p.pubdate_utc
, DATE_FORMAT(p.pubdate_utc, '%d %b') AS post_date
, DATE(p.pubdate_utc) AS mydate
, (pp.comments + pp.likes + pp.favorites) AS score
FROM posts p 
INNER JOIN posts_points pp ON p.post_id = pp.post_id
INNER JOIN 
(
    SELECT p.pubdate_utc AS max_date, 
    (pp.comments + pp.likes + pp.favorites) AS max_score
    FROM posts p2 
    INNER JOIN posts_points pp2 ON p2.post_id = pp2.post_id
) m ON score = m.max_score
AND mydate = m.max_date
ORDER BY mydate DESC
LIMIT 18;

答案 4 :(得分:0)

你可以看到这个查询。内部查询首先获取那些在两个表中具有相同post_id的行而不是sum(pp.comments + pp.likes + pp.favorites)作为得分.Outer Query是获取最大分数并且正在执行组截止日期......

SELECT post_id, profile_id
   , MAX(score)
   , DATE_FORMAT(pubdate_utc, '%d %b') post_date
   , DATE(pubdate_utc) as mydate
FROM
(
   SELECT p.profile_id, p.post_id, p.pubdate_utc
      , (pp.comments + pp.likes + pp.favorites) AS score
   FROM posts p 
   INNER JOIN posts_points pp ON p.post_id = pp.post_id
) 
GROUP BY pubdate_utc
ORDER BY pubdate_utc DESC