【问题标题】:MySQL: GROUP by with multiple columnsMySQL:按多列分组
【发布时间】:2016-11-30 16:29:03
【问题描述】:

我正在尝试从表中获取多个值,其中 GROUP BY 仅针对其中一列。为简化起见,我将使用模型留言簿表作为示例:

postNumber | user | text        | date | portal
-----------------------------------------------
 1 | Michael      | "nice blog" | 10/12| fitness
 2 | Ronald       | "hello!"    | 12/12| lounge
 1 | Michael      | "beautiful" | 05/11| pictures
 2 | Sandra       | "great pic" | 10/12| pictures

假设留言簿的首页必须打印最新的来宾帖子,但每个门户(健身、休息室和图片)只能打印一个。期望的结果是:

  • michael/“不错的博客”/健身
  • 罗纳德/“你好”/休息室
  • 和 sandra/“好照片”/图片。

排除的帖子将是 Michael/"beautiful"/pictures,因为它不是该门户的最新帖子。

以下查询对于更现代的 mySQL 服务器无效,抛出如下所述的错误:

SELECT max(postNumber), user, text, date, portal FROM guestbook GROUP BY portal;

GROUP BY 子句并包含非聚合列“database.table.columnName”,它在功能上不依赖于 GROUP BY 子句中的列;这与 sql_mode=only_full_group_by 不兼容

但是,下面这个更有限的查询可以实现预期的结果,但它不能影响其余需要的列(用户、文本、日期),这正是我遇到的问题:

SELECT max(postNumber), portal FROM guestbook GROUP BY portal;

需要注意的是,可以通过将用户、文本和日期添加到 GROUP BY 来修复第一个查询,但是像这样进行复合分组将不再每个门户仅检索一个条目。

如果有人对此问题有解决方案,请详细说明,因为我自己或通过在线研究无法找到方法。

编辑:我尝试了以下查询,但没有结果,因为 RIGHT JOIN 为我提供了左表中的值(仅门户和帖子编号),不确定原因:

'SELECT t1.portal, max(t1.postNumber) from guestbook t1 RIGHT OUTER JOIN (SELECT * from guestbook) t2 on t1.postNumber = t2.postNumber GROUP BY portal LIMIT ?';

【问题讨论】:

  • 您可以尝试按照in this answer的描述禁用 only_full_group_by
  • 我明白了,但据我所知,现在 only_full_group_by 是默认值的原因是,否则它可能会产生松散、随机的结果,最好制作更坚固的 SQL。如果可能的话,我想实现一个与新的 mySQL 默认设置兼容的解决方案

标签: mysql group-by


【解决方案1】:

您走在正确的轨道上...根据您想要的记录进行预查询,然后在符合条件的日期条件下重新加入同一个原始表..

select
      PreQuery.Portal,
      PreQuery.LatestPostNumber,
      T2.User,
      T2.Text,
      T2.Date
   from
      ( select 
              t1.Portal,
              max( t1.PostNumber ) as LatestPostNumber
           from
              GuestBook T1
           group by 
              t1.Portal ) PreQuery
         JOIN GuestBook T2
            on PreQuery.Portal = T2.Portal
           AND PreQuery.PostNumber = T2.PostNumber

【讨论】:

  • 非常感谢 DRapp。虽然您的查询本身在我的本地主机上返回“零”(可能是由于我的错),但您的示例让我更清楚。我需要一个额外的“AND”,这样我的查询才能正确加入。这是我目前的查询,到目前为止正在返回预期的结果:'SELECT t1.parentID, t1.imageFileExtension, t1.postNumber, t1.postBoardDirectory, t1.user FROM posts t1 JOIN (SELECT postBoardDirectory as PBD, max(postNumber) as MAXNUM from posts GROUP BY PBD ) t2 on t1.postNumber = MAXNUM AND t1.postBoardDirectory = PBD LIMIT 15';如果我遇到新的查询问题,我会更新这篇文章
  • @R.M.D,很高兴为您提供帮助,还请查看帮助 -> 了解有关此问题和您的其他问题的网站礼仪。如果帖子确实有效,或直接帮助您解决问题(如这个),则标记为已回答。然后,如果其他人有类似的问题,他们也会看到什么有效以及为什么。
  • @R.M.D,还有一点。不要将 cmets 用于代码示例。编辑您的原始帖子,将更改放在那里,然后添加评论以要求此人查看您的更改,以防您需要进一步跟进。
【解决方案2】:

请尝试以下查询

SELECT *
FROM (SELECT postNumber, 
             user, 
             text,
             date,
             @current_portal := portal,
             @portal_rank := IF(@current_portal = portal and @portal_rank = portal, @portal_rank + 1, 1) AS portal_rank,
      FROM guestbook
      ORDER BY portal, date DESC) ranked
WHERE portal_rank = 1)

使用 portal_rank 变量对门户进行排名,并按门户和日期顺序排列。 这样,您只为每个门户选择最新记录

我认为这个查询更容易理解,当您可以使用变量时,无需在单个表上执行多个连接。

另外切换条件 portal_rank = 1 与 portal_rank 可以说

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-25
    • 1970-01-01
    相关资源
    最近更新 更多