【问题标题】:Not getting grouped results when using GROUP BY on a string column在字符串列上使用 GROUP BY 时未获得分组结果
【发布时间】:2019-07-27 09:49:53
【问题描述】:

我有一个收件箱表,我想在其中返回按电话号码分组的消息(例如按发件人分组的 GMail 组)。并且 sms_content 应该是 id 的最后一条消息。但是当我使用 GROUP BY 关键字时,它不会返回分组结果。

这是我的“收件箱”表。有 2 条来自号码“+123456789”的消息应该被分组。

+----+--------------+------------------------------+
| id | phone_number |         sms_content          |
+----+--------------+------------------------------+
|  1 | +123456789   | Hello, my name is            |
|  2 | +987654321   | What's up, long time no see! |
|  3 | +123456789   | John, I want to meet you!    |
+----+--------------+------------------------------+

我的第一个查询失败并显示此错误消息

select * from inbox group by phone_number

错误:查询错误:错误:列“inbox.id”必须出现在 GROUP BY 子句或在聚合函数中使用

我尝试的第二个查询没有返回按电话号码分组的结果

select *
from inbox
group by phone_number, id, sms_content
order by id desc

结果(未分组):

+----+--------------+------------------------------+
| id | phone_number |         sms_content          |
+----+--------------+------------------------------+
|  3 | +123456789   | John, I want to meet you!    |
|  2 | +987654321   | What's up, long time no see! |
|  1 | +123456789   | Hello, my name is            |
+----+--------------+------------------------------+

我希望看到的结果是这样的。电话号码字段应分组,sms_content 应显示该电话号码的最新 sms_content。

+--------------+------------------------------+
| phone_number |         sms_content          |
+--------------+------------------------------+
| +123456789   | John, I want to meet you!    |
| +987654321   | What's up, long time no see! |
+--------------+------------------------------+

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

    对于这种情况,PostgreSQL 有一个有用的标准扩展:

    SELECT DISTINCT ON (phone_number)
           phone_number,
           sms_content
    FROM inbox
    ORDER BY phone_number, id DESC
    

    Details:

    SELECT DISTINCT ON ( expression [, ...] ) 只保留给定表达式计算结果等于的每组行的第一行。

    (Sample fiddle)

    【讨论】:

    • 这看起来很优雅,可惜只适用于 PostgreSQL。但就我而言,这就是我所需要的。谢谢!
    • 你指定了PostgreSQL,当然你会得到PostgreSQL的答案。
    【解决方案2】:

    先获取每个数字的最大id,然后加入表:

    select i.phone_number, i.sms_content
    from inbox i inner join (
      select phone_number, max(id) maxid
      from inbox 
      group by phone_number
    ) g on g.maxid = i.id and g.phone_number = i.phone_number
    

    或不存在:

    select i.phone_number, i.sms_content
    from inbox i
    where not exists (
      select 1 from inbox
      where phone_number = i.phone_number and id > i.id
    )
    

    【讨论】:

    • 另外,所有答案中最快的执行时间。
    【解决方案3】:

    试试这个:

    select id,phone_number
          ,sms_content
    
    from inbox
    
    where id in(
                Select MAX(id) AS id
                FROM inbox
                group by phone_number
                    )
    

    【讨论】:

      【解决方案4】:

      你可以像这样使用row_number:

      select * from (   
           select phone_number, sms_content, 
           row_number() over(partition by phone_number order by id desc) as rn
           from inbox
      ) t
      where 
      rn = 1
      

      【讨论】:

      • 简单地对消息进行分组似乎过于复杂。是否可以在更简单的查询中做到这一点?
      【解决方案5】:

      选择最大(id),电话号码, 收件箱中的 sms_content 按电话号码分组

      【讨论】:

      • 错误:列“inbox.sms_content”必须出现在 GROUP BY 子句中或用于聚合函数中
      猜你喜欢
      • 1970-01-01
      • 2011-01-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多