场景

有一张得分表(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. python中一些内置函数实例

    lambda表达式 简单函数可用lambda表达式 1. def f1() return(123) r1=f1() print() 2. f2=lambda:123 r2=f2() print() 以 ...

  2. Educational Codeforces Round 47 (Rated for Div. 2) :E. Intercity Travelling

    题目链接:http://codeforces.com/contest/1009/problem/E 解题心得: 一个比较简单的组合数学,还需要找一些规律,自己把方向想得差不多了但是硬是找不到规律,还是 ...

  3. 为什么我要放弃javaScript数据结构与算法(第一章)—— JavaScript简介

    数据结构与算法一直是我算比较薄弱的地方,希望通过阅读<javaScript数据结构与算法>可以有所改变,我相信接下来的记录不单单对于我自己有帮助,也可以帮助到一些这方面的小白,接下来让我们 ...

  4. python2.7入门---运算符 &案例

        已经分享过变量类型的基本概念了,接下来就研究了一下运算符的基础知识.接下来我们就来看一下内容.举个简单的例子 4 +5 = 9 .例子中,4 和 5 被称为操作数,"+" ...

  5. C# 控制台应用程序输出颜色字体

    最佳解决方案的代码: static void Main(string[] args) { Console.ForegroundColor = ConsoleColor.Green; Console.W ...

  6. vs2013中将复制过来的文件或文件夹显示到解决方案管理

    先将文件夹和文件复制到VS程序所在的位置,在VS2013解决方案资源管理器中找到这些文件所在的上一级文件夹,先将那个上层文件夹收缩起来,然后再点击解决方案资源管理器上的“显示所有文件”按纽,展开这个文 ...

  7. javascript-es6学习笔记

    es6技术培训文档 第一阶段:1.let与const用法2.变量的解构赋值3.字符串的扩展4.正则的扩展5.数组的扩展6.函数的扩展7.对象的扩展8.Symbol9.Set和Map数据结构 第二阶段: ...

  8. C#属性默认值设置

    关于在MVC中view中设置默认值,可以象如下设置: 1.关于VIEWMODEL的部分 如果是C#  6.0,网上资料查到说可以 如果语法不支持,只能改回.net 2.0的写法. public cla ...

  9. C#获取网络图片

    简单获取图片 string url = zhi_txt.Text;//图片地址 string dizhi = lujing.Text;//图片下载后保存路径及图片名称要写在一块 WebClient w ...

  10. JDBC剖析篇(2):JDBC之PreparedStatement

    一次有人问我为什么要使用JDBC中的PreparedStatement,我说可以“防止SQL注入”,其他的却不能说出个一二三,现在来看看其中的秘密 参考文章: http://www.jb51.net/ ...