sql如何先排序再去重
场景
有一张得分表(score),记录了用户每次的得分,同一个人可能有多个得分。
id | name | score |
---|---|---|
1 | tom | 45 |
2 | jack | 78 |
3 | tom | 34 |
. | . | . |
需求:找出分数最高的前5个人。
SQL1
首先我们写个最简单的sql:
select
id, name, score
from
score
order by
score desc
limit 5;
如果sql这样写,结果可能是:
id | name | score |
---|---|---|
2 | jack | 78 |
1 | tom | 45 |
3 | tom | 34 |
排序了,但是没有去重
SQL2
那么我们加上去重:
select
distinct name
from
score
order by
score desc
limit 5;
首先第一点是这个sql未必能执行。在一些数据库版本,这个sql可以被执行,在一些版本则会提示你order by的字段必须在distinct中存在(见SQL3)。
但是即使能执行,这个sql也得不到预期结果。原因是distinct优先于order by 被数据库执行。
在执行distinct name的时候,如上文中的数据。是取id=1的数据,还是id=3的数据呢?其实这是数据库自行决定的。因此,可能会不正确选择数据。
比如真的执行这个sql,可能去重的结果是:
id | name | score |
---|---|---|
2 | jack | 78 |
3 | tom | 34 |
然后再执行一个order by,就会认为第一名是jack78分,第二名是tom34分。然而其实tom应该是45分,这个45分就在数据库执行distinct的时候被错误的丢弃了,毕竟先执行distinct的时候不知道你到底要哪个数据。
SQL3
那么我们把score加入select中呢?
select
distinct name, score
from
score
order by
score desc
limit 5;
很明显,这样写的执行结果和我们预期不符。因为如果写:distinct name,score实际上是对name和score一起去重。比如name都是jack,score都是45。那么这行就会被去掉。
但是问题是正因为把score当做去重的条件了。所以对于同名的人,比如都叫tom,会因为其有两个分数,导致不能被去重,从而保留两行记录。结果就是好像没有去重。
SQL4
那我不用distinct,用group by进行去重可以吗?
select
name
from
score
group by
name
order by
score desc
limit 5;
也不行,因为在group by的时候,数据库还是不知道对两行name一样的数据,究竟应该留下哪一行。
SQL5
正确的写法:
select
name
from
score
group by
name
order by
max(score) desc
limit 5;
这样写,在执行group by的时候,数据库就知道要保留score最大的那一行了。
sql如何先排序再去重的更多相关文章
- 不简单的SQL查询和排序语句
真不简单!! 一:使用select语句进行查询 语法: SELECT <列名> FROM <表名> [WHERE <查询条件表达式>] [OR ...
- mysql 怎样先排序再分组
权游游牧族:众所周知!一句SqL语句不能先排序再分组.所以这里给出几个案例 --表结构-- create table `shop` ( `id` int (10) PRIMARY KEY, `shop ...
- SQL语句分组排序,多表关联排序
SQL语句分组排序,多表关联排序总结几种常见的方法: 案例一: 在查询结果中按人数降序排列,若人数相同,则按课程号升序排列? 分析:单个表内的多个字段排序,一般可以直接用逗号分割实现. select ...
- 帝国CMS系统标签e:loop调用的附加SQL条件和排序参数
帝国CMS6.5以上版本在原来所有信息调用标签基础上增加了两个标签参数:“附加SQL条件”和“显示排序”.支持这两个参数的标签有如下:ecmsinfo.灵动标签.phomenews.phomenews ...
- SQL SERVER 的排序规则
有时候查询数据库的时候会发现(比如做重名检查的时候):数据库的查询时对大小写不敏感的,也就是 A 和 a 是一样的. 也就是说 select * from tabletest where name = ...
- SQL Server更改排序规则的实现过程
摘自: http://www.2cto.com/database/201112/115138.html 以下的文章主要向大家描述的是SQL Server更改排序规则的实现过程,以及在实现其实际操作过程 ...
- Spring data JPA先排序再分页。
//工具类,增删改查等等package com.yunqing.service.impl; import java.util.Map; import org.springframework.beans ...
- java对一个int数组进行排序、去重
思路: 1.使用 HashSet 进行去重 2.将 HashSet 变为 TreeSet 3.使用 TreeSet 进行排序 4.将 Set 变为 Integer 数组 5.将 Integer 数组变 ...
- 页面上有3个输入框:分别为max,min,num;三个按钮:分别为生成,排序,去重;在输入框输入三个数字后,先点击生成按钮,生成一个数组长度为num,值为max到min之间的随机整数点击排序,对当前数组进行排序,点击去重,对当前数组进行去重。 每次点击之后使结果显示在控制台
<!DOCTYPE html> <html> <head> <!-- 页面上有3个输入框:分别为max,min,num:三个按钮:分别为生成,排序,去重: 在 ...
随机推荐
- raid概述与CentOS7.4中raid5的搭建与测试
前言 一.raid的定义与作用 raid(独立冗余磁盘阵列).raid技术通过把多个硬盘设备组合成一个容量更大的,安全性更好的磁盘阵列.把数据切割成许多区段后分别放在不同的物理磁盘上,然后利用分散读写 ...
- 03 shell编程之case语句与函数
本文所有内容均来自当年博主当年学习笔记,若有不足欢迎指正 Shell编程之case语句与函数 学习目标: 掌握case语句编程 掌握shell函数的使用 目录结构: Case语句 Case语句的作用 ...
- Git推送到远程分支出错
执行git push -u origin master fatal: 'git@github.com:qilinonline/git_test.git' does not appear to be a ...
- jquery把数组中年月相同的数组重新组成新的数组
//原数组var data = { results: [{ id:0, date:'2017-12-12', content:'123' },{ id:0, date:'2017-12-12', co ...
- 【redis常用的键值操作及性能优化】
服务端 启动redis服务 { // -a:指定密码 -h:指定主机 -p:指定端口 } //让redis 服务中断崩溃 //保存和关闭 //后台备份 //设置登录密码 //redis-benchma ...
- 深入理解is_callable和method_exists
一.函数解析 is_callable() 定义: (PHP 4 >= 4.0.6, PHP 5, PHP 7) is_callable — 检测参数是否为合法的可调用结构 bool is_cal ...
- python函数的返回值
返回值:return1.没有返回值 #不写return #只写return:结束一个函数 #return None2.有一个返回值 #可以返回任何数据类型 #只要返回就可 ...
- R语言绘图:词云图
使用wordcloud2绘制词云图 library(wordcloud2) findwords<-function(tf){ txt<-scan(tf,"") wl&l ...
- Using ARR to setup a proxy
Install IIS Install ARR 3.0 from WebPI Open IIS management console (inetmgr), select the server node ...
- Java并发基础--线程通信
java中实现线程通信的四种方式 1.synchronized同步 多个线程之间可以借助synchronized关键字来进行间接通信,本质上是通过共享对象进行通信.如下: public class S ...