场景

有一张得分表(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如何先排序再去重的更多相关文章

  1. 不简单的SQL查询和排序语句

    真不简单!! 一:使用select语句进行查询 语法: SELECT    <列名> FROM      <表名> [WHERE    <查询条件表达式>] [OR ...

  2. mysql 怎样先排序再分组

    权游游牧族:众所周知!一句SqL语句不能先排序再分组.所以这里给出几个案例 --表结构-- create table `shop` ( `id` int (10) PRIMARY KEY, `shop ...

  3. SQL语句分组排序,多表关联排序

    SQL语句分组排序,多表关联排序总结几种常见的方法: 案例一: 在查询结果中按人数降序排列,若人数相同,则按课程号升序排列? 分析:单个表内的多个字段排序,一般可以直接用逗号分割实现. select ...

  4. 帝国CMS系统标签e:loop调用的附加SQL条件和排序参数

    帝国CMS6.5以上版本在原来所有信息调用标签基础上增加了两个标签参数:“附加SQL条件”和“显示排序”.支持这两个参数的标签有如下:ecmsinfo.灵动标签.phomenews.phomenews ...

  5. SQL SERVER 的排序规则

    有时候查询数据库的时候会发现(比如做重名检查的时候):数据库的查询时对大小写不敏感的,也就是 A 和 a 是一样的. 也就是说 select * from tabletest where name = ...

  6. SQL Server更改排序规则的实现过程

    摘自: http://www.2cto.com/database/201112/115138.html 以下的文章主要向大家描述的是SQL Server更改排序规则的实现过程,以及在实现其实际操作过程 ...

  7. Spring data JPA先排序再分页。

    //工具类,增删改查等等package com.yunqing.service.impl; import java.util.Map; import org.springframework.beans ...

  8. java对一个int数组进行排序、去重

    思路: 1.使用 HashSet 进行去重 2.将 HashSet 变为 TreeSet 3.使用 TreeSet 进行排序 4.将 Set 变为 Integer 数组 5.将 Integer 数组变 ...

  9. 页面上有3个输入框:分别为max,min,num;三个按钮:分别为生成,排序,去重;在输入框输入三个数字后,先点击生成按钮,生成一个数组长度为num,值为max到min之间的随机整数点击排序,对当前数组进行排序,点击去重,对当前数组进行去重。 每次点击之后使结果显示在控制台

    <!DOCTYPE html> <html> <head> <!-- 页面上有3个输入框:分别为max,min,num:三个按钮:分别为生成,排序,去重: 在 ...

随机推荐

  1. raid概述与CentOS7.4中raid5的搭建与测试

    前言 一.raid的定义与作用 raid(独立冗余磁盘阵列).raid技术通过把多个硬盘设备组合成一个容量更大的,安全性更好的磁盘阵列.把数据切割成许多区段后分别放在不同的物理磁盘上,然后利用分散读写 ...

  2. 03 shell编程之case语句与函数

    本文所有内容均来自当年博主当年学习笔记,若有不足欢迎指正 Shell编程之case语句与函数 学习目标: 掌握case语句编程 掌握shell函数的使用 目录结构: Case语句 Case语句的作用 ...

  3. Git推送到远程分支出错

    执行git push -u origin master fatal: 'git@github.com:qilinonline/git_test.git' does not appear to be a ...

  4. jquery把数组中年月相同的数组重新组成新的数组

    //原数组var data = { results: [{ id:0, date:'2017-12-12', content:'123' },{ id:0, date:'2017-12-12', co ...

  5. 【redis常用的键值操作及性能优化】

    服务端 启动redis服务 { // -a:指定密码 -h:指定主机 -p:指定端口 } //让redis 服务中断崩溃 //保存和关闭 //后台备份 //设置登录密码 //redis-benchma ...

  6. 深入理解is_callable和method_exists

    一.函数解析 is_callable() 定义: (PHP 4 >= 4.0.6, PHP 5, PHP 7) is_callable — 检测参数是否为合法的可调用结构 bool is_cal ...

  7. python函数的返回值

    返回值:return1.没有返回值    #不写return    #只写return:结束一个函数    #return None2.有一个返回值    #可以返回任何数据类型    #只要返回就可 ...

  8. R语言绘图:词云图

    使用wordcloud2绘制词云图 library(wordcloud2) findwords<-function(tf){ txt<-scan(tf,"") wl&l ...

  9. Using ARR to setup a proxy

    Install IIS Install ARR 3.0 from WebPI Open IIS management console (inetmgr), select the server node ...

  10. Java并发基础--线程通信

    java中实现线程通信的四种方式 1.synchronized同步 多个线程之间可以借助synchronized关键字来进行间接通信,本质上是通过共享对象进行通信.如下: public class S ...