在字符串列上使用 GROUP BY 时未获得分组结果
Posted
技术标签:
【中文标题】在字符串列上使用 GROUP BY 时未获得分组结果【英文标题】:Not getting grouped results when using GROUP BY on a string column 【发布时间】: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! |
+--------------+------------------------------+
【问题讨论】:
【参考方案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 子句中或用于聚合函数中以上是关于在字符串列上使用 GROUP BY 时未获得分组结果的主要内容,如果未能解决你的问题,请参考以下文章
MySQL在分组(GROUP BY)结果上使用ORDER BY