sql如何先排序再去重

sql如何先排序再去重

场景

有一张部分(chat)表,记录了用户群组每次的聊天,同一个人可能在多个房间有多个聊天。
(id::id ,u_id:用户id,content:聊天内容,room_id:聊天房间,is_status:0未读 1已读)

idu_idcontentroom_idis_status
12您好163037991561130
21您好163037991561131
32您好呀163037991561130
41您好163074670730080
52您好163074670730080
63您好163074670730080
71您好163074670730080

需求:找出每个聊天房间里最新没有读的消息。

SQL.1

首先我们写个最简单的sql:

select 
	id,u_id,content,room_id,is_status
from 
	chat
order by 
	room_id desc

如果sql这样写,结果可能是:

idu_idcontentroom_idis_status
12您好163037991561130
21您好163037991561131
32您好呀163037991561130
41您好163074670730080
52您好163074670730080
63您好163074670730080
71您好163074670730080

排序了,但是没有去重

SQL.2

那么我们加上去重:

select 
	distinct u_id 
from 
	chat
order by 
	room_id desc

首先第一点是这个sql未必能执行。
在一些数据库版本,这个sql可以被执行,在一些版本则会提示你order by的字段必须在distinct中存在
但是即使能执行,这个sql也得不到预期结果。原因是distinct优先于order by 被数据库执行。
比如真的执行这个sql,可能去重的结果是:

idu_idcontentroom_idis_status
12您好163037991561130
41您好163074670730080

在执行distinct room_id的时候,如上文中的数据。是取id=1的数据,还是id=3的数据呢?其实这是数据库自行决定的。因此,可能会不正确选择数据。

那么我们把room_id加入select中呢?

select 
	distinct u_id , room_id
from 
	chat
order by 
	room_id desc

很明显,这样写的执行结果和我们预期不符。

但是问题是正因为把room_id当做去重的条件了。所以对于相同的人,比如都是16303799156113,会因为其有两个数据,导致不能被去重,从而保留两行记录。结果就是好像没有去重

SQL.3

那我不用distinct,用group by进行去重可以吗?

select 
	u_id
from 
	chat
group by
	room_id
order by 
	room_iddesc

也不行,因为在group by的时候,数据库还是不知道对两行u_id一样的数据,究竟应该留下哪一行。

正确的写法:

select 
	u_id
from 
	chat
group by
	room_id
order by 
	max(id) desc

这样写,在执行group by的时候,数据库就知道要保留id最大的那一行了。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
1.查看有哪些数据库 2.新建数据库 3.使用数据库(在我们的密令行中要使用数据库 才能进行相应的建表 查询等操作) 4.创建一个数据库表 create table 表名 ( id 类型 约束 , 列名 类型 约束 , 列名 类型 约束 ) 5.查看数据库表 6.查看数据库表结构 7.添加数据 A . insert into 表名 (列名1,列名2.。。。) values (值1,值2。。。) 注意:1 id 是主键自增的 所以我们添加的时候 不去管id 因为它会自动增加 2 在添加的时候 有多少列 就要有多少个值 3 并且类型要匹配 B. 注意 :1 没有添加列名 代表所有列都添加数据 (id,name , age) 所以我们的值 也需要 3个 (null,’zhangsan’,18) 2 因为id是自增 所以我们第一个值写 null C. 8.查询表中所有的数据 SELECT * FROM 表名; Where 条件 9.条件删除 delete from 表名 where 条件; 10.修改 Update 表名 set 列 = 值 ,列=值 where 条件 11.删除table 12.删除数据库 二.查询语句 13.查询语句 Select 列名 from 表名 查询出的结果 称之为 临时表 我们可以订制临时表有那些列 14.查询的时候 可以给 表 或者 列 起别名 Select 列名1 [as] 别名 , 列名2 [as] 别名2 from 表名 别名 15.去重查询 16.条件查询 练习1 年龄大于 25的学生 > < >= <= != <> = 17.多条件查询 & and || or 18.条件查询 (模糊搜索) like %零个或多个 _匹配一个 19.排序 order by 列名 注意 如果只写列名 代表 升序。 升序 asc 降序 desc 如果需要多列排序,可以指定第二排序原则 三.聚合函数 20.Count 查询有多少条数据 21.Max 查询某一列最大值 22.Min 查询某一列最小值 23.Avg 查询某一列的平均值 24.Sum 查询某一列的总和 25.分组查询 group by 列 26.分组条件查询 having 查询平均年龄大于25以上的班级和班级平局年龄 27.数据库分页语句 limit limit (索引,长度) 28.多表查询 Select 列名 from 表名1,表名2 29.笛卡尔乘积 (A,B) (c,d) => Ac Ad Bc Bd 30.内连接查询 A.隐式内连接 B.显示内连接 inner join on Select 列名 from 表 inner join 表1 on 条件 31.外连接查询 左外链接 需求:查询所有学生 如果有班级的 显示班级。 此时我们再去用内连接进行查询 那么 新学生查询不出来 所以我们需要用到外连接 left join on 左外链接 就是 左边表的数据全部查询 右边表符合条件的查询出来 右外链接 32.子查询 注意 子查询的结果 一定要和 另一个查询条件匹配

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小*-^-*九

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值