产品操作MySQL第5篇 – 数据查询-排重查询

产品操作MySQL第5篇 – 数据查询-排重查询

MYSQL

本资料为产品岗位作为日常工作参考,语言口语化

At 2019/4/22 By David.Yang

排重查询(使用DISTINCT运算符来消除结果集中的重复行)

针对现有业务数据进行查询时,会有重复的数据记录,

有时候我们需要进行排重的数据查询,为了避免重复数据,

我们通常使用DISTINCT进行处理。

语法:

SELECT DISTINCT

column[,column...]

FROM

table_name

WHERE

where_conditions;

这个查询语法我们在看完SELECT语法后应该比较熟悉了。

其中column可以是多个字段哦~

DISTINCT语句演示

为了进行数据演示,我们将学生表加入国家字段,代表各个学生的国际都是哪些。

不知道大家是否还记得怎么对数据表进行字段新增的?

SQL

ALTER TABLE `students` ADD `nationality` varchar(20) COMMENT '国籍' AFTER `age`;


产品操作MySQL第5篇 – 数据查询-排重查询


然后把数据补进去。

然后呢?

校长先生想看看今年的学生招收情况,这些学生都来自哪些国家?

我们教导主任周伯通,这可就难为了,

因为他知道,想要知道所有学生的国籍呢,

这个简单啊,他会,

只要这么做就行了

SQL

SELECT

nationality

FROM

students;


产品操作MySQL第5篇 – 数据查询-排重查询


周伯通一看好开心呀~

看,学生来自五湖四海,大江南北啊,有南宋的,有西辽的,有西夏的,

看来俺们这学校声誉不错啊。

等等,咋是南宋、南宋一样一样的呢?

可是这不行啊,校长要的是生源地,怎么还有重复的呢?

这可愁坏了教导主任周伯通。

怎么才能去掉重复的呢?

这旁边一看坐的谁啊?

老情敌一灯大师啊!

没办法,校长的任务还得干,

没什么不好意思的,问吧

“额,那啥,一灯”

“当年是我不对啊,抢了你媳妇儿瑛姑”

“你都当和尚了,也就不计较了,咱进行个学术讨论啊”

“讷啥,你看看我这校长给的统计生源的事儿,你给瞅一眼呗”

一灯答:“行”

“看老衲给你点拨一二”

一灯的SQL是这么写的

SQL

SELECT DISTINCT

nationality

FROM

students;


产品操作MySQL第5篇 – 数据查询-排重查询


一灯“牛逼不,就一字儿”

“嗯… 嗯~”

以上,就说明了DISTINCT关键字是干什么的了,他成功的消除了重复项。

DISTINCT多列怎么用

一灯曰“再给你开个光,瞅瞅多个列会有啥效果”

SQL

SELECT DISTINCT

nationality, gender

FROM

students;


产品操作MySQL第5篇 – 数据查询-排重查询


结果集会告诉你南宋下的生源有男、女性别,

西夏就不同了,只有姑娘,没有男娃儿。

以上假如我们还有学生的县府数据,上边的示例变通一下,

我们是不是就可以获得国籍– 府县了呢?

比如:

SELECT DISTINCT

nationality,州字段

FROM

students;

南宋– 京兆府

南宋– 延安府

南宋– 商州

南宋– 同州

南宋– 华州

如果不是有DISTINCT语句控制,你得到的数据将会是

南宋– 京兆府

南宋– 京兆府

南宋– 京兆府

南宋– 延安府

南宋– 延安府

南宋– 延安府

南宋– 商州

南宋– 商州

南宋– 商州

南宋– 同州

南宋– 华州

DISTINCT对NULL值的处理

我们再招一个洋学生,叫路易11,不设置他的国籍,

数据库对应国籍为NULL,我们看看会是什么结果?

SQL

SELECT DISTINCT nationality FROM students;


产品操作MySQL第5篇 – 数据查询-排重查询


DISTINCT对NULL类型数据是不进行过滤的,

即返回结果集中会包含NULL的值。

那我们要排除NULL的空数据呢?

可以直接在WHERE条件中加以限制。

SQL

SELECTDISTINCTROW

nationality

FROM

students

WHERE

nationality IS NOT NULL;


产品操作MySQL第5篇 – 数据查询-排重查询


注:后续过滤查询会讲解WHERE子句

DISTINCT对*值的处理

mysql> SELECT DISTINCT * FROM students;


产品操作MySQL第5篇 – 数据查询-排重查询


这时候其实等价于:

SELECT DISTINCT

nationality,gender, xxx, xxx, xxx, …

FROM

students;

DISTINCT与LIMIT

我们前文提起过LIMIT,用来限制返回的数据记录条数,

这里也同样可以使用。

SQL

SELECT DISTINCTROW

nationality

FROM

students

LIMIT 3;


产品操作MySQL第5篇 – 数据查询-排重查询


注:后续过滤查询会讲解LIMIT子句

DISTINCT与GROUP BY子句比较

GROUP BY看字面意思聚合,分组,我们大概就能想到,

他与DISTINCT多少有点关系,或能做差不多的事情,

你别说,还真是。

比如我们要用GROUP BY来实现生源地统计,该怎么做呢?

一灯大师会这么做:

SQL

SELECT

nationality

FROM

students

GROUP BY

nationality;


产品操作MySQL第5篇 – 数据查询-排重查询


一灯说“瞅见没,一样一样的”

“不对呀,不是一样一样的撒,这不顺序不太一样么?和尚”

确实,顺序是不一样。

一般来说,DISTINCT和GROUP

BY字句能干差不多的事,

那我们要是给DISTINCT加个排序呢?

(别慌,排序我们后文会讲的,现在留个印象日后好相处)

SQL

SELECT DISTINCT

nationality

FROM

students

ORDER BY

nationality;


产品操作MySQL第5篇 – 数据查询-排重查询


DISTINCT与聚合函数的组合使用

SQL当中有一些聚合函数,比如SUM/COUNT/AVG等等,

他们可以用来与DISTINCT组合使用进行一些业务场景的查询。

-- 统计班级性别的分布情况

SQL

SELECT

gender, COUNT(DISTINCT number)

FROM

students

GROUP BY

gender;


产品操作MySQL第5篇 – 数据查询-排重查询


因为学号是学生的标记,我们通过DISTINCT就可以排除重复学号数据,

在通过COUNT进行计数统计,

后然通过gender进行分组;

再比如统计学生年龄分布,可以这么写:

SQL

SELECT

age, COUNT(DISTINCT number)

FROM

students

GROUP BY

age;


产品操作MySQL第5篇 – 数据查询-排重查询


注:

此种场景不能脱离GROUP BY字句。

-- 统计学生最大年龄,并统计有多少人?

SQL

SELECT

max(age), COUNT(DISTINCT number)

FROM

students

WHERE

age = (SELECT max(age) FROM students);


产品操作MySQL第5篇 – 数据查询-排重查询


当然你也可以加上条件进行查询,

比如看来自西夏的学生最大年龄是多少,有多少人?

SQL

SELECT

nationality, max(age), COUNT(DISTINCTnumber)

FROM

students

WHERE

nationality = '西夏'

AND

age = (SELECT max(age) FROM studentsWHERE nationality = '西夏');


产品操作MySQL第5篇 – 数据查询-排重查询


SQL解释

ϒ以上在WHERE当中使用了子查询,需要通过子查询先算出最大年龄是多少,再进行外围SQL的查询。

所以你如果这么写,就会报错

SQL ERROR

SELECT

max(age), COUNT(DISTINCT number)

FROM

students

WHERE

age = max(age);

错误提示:


产品操作MySQL第5篇 – 数据查询-排重查询


为什么呢?

聚集函数也叫列函数,它们都是基于整列数据进行计算的,

而where子句则是对数据行进行过滤的(这里过滤是在一个记录里边过滤的,基于"行"),

在筛选过程中依赖“基于已经筛选完毕的数据得出的计算结果”是一种悖论,

这是行不通的。

更简单地说,因为聚集函数要对全列数据时行计算,

因而使用它的前提是:结果集已经确定!

而where子句还处于“确定”结果集的过程中,因而不能使用聚集函数。

ϒ如果你需要再进一步限定WHERE条件,那么请再子查询和WHERE条件内进行条件的操作

比如前面例子,我只想统计来自西夏的学生,

那么你需要现统计出西夏学生的最大年龄,这个在子语句中实现,

这时候你已经得到了西夏的行数据中年龄列的最大值;

在外部WHERE查询时,时针对整体行进行查询,

所以他需要对条件【国籍=西夏】进行限定,使得过滤出【国籍=西夏】的数据。

WHERE和子语句组合使用使得你查询的数据保持正确性。

如果在子查询中使用了【国籍=西夏】的条件,

而WHERE并为进行条件过滤,那么你其实是在做这么一件事,

通过子语句得到一个最大值的年龄,比如16,

然后查询所有【国籍=所有】学生,年龄=16的学生,共有多少人。

SQL

SELECT

max(age), COUNT(DISTINCT number)

FROM

students

WHERE

age = (SELECT max(age) FROM students WHERE nationality = '西夏');


产品操作MySQL第5篇 – 数据查询-排重查询


但其实西夏的最大年龄16岁,学生只有1个

正确结果


产品操作MySQL第5篇 – 数据查询-排重查询


本篇章讲解了查询中消除重复行的相关语法,

到此你应该能够进行数据去重复业务上相关的数据操作。

Bye Bye.


分享到:


相關文章: