SQL Distinct的实现

本文介绍了SQL中的Distinct操作,包括其效果、实现方法(排序法与哈希法),并对比了Distinct与Group By的区别。通过实例展示了如何从数据库中筛选出唯一的记录。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Distinct是SQL中一种很常见的操作,能够很方便地筛选掉结果中重复的行。首先来看看Distinct操作的效果:

mysql> select * from ob;
+------+------+------+
| a | b | c |
+------+------+------+
| 1 | 2 | 3 |
| 1 | 2 | 3 |
| 1 | 2 | 3 |
| 1 | 2 | 2323 |
| 1 | 323 | 21 |
| 9 | 9 | 9 |
+------+------+------+
6 rows in set (0.00 sec)


/// 取出所有不同行

mysql> select distinct * from ob;

+------+------+------+
| a | b | c |
+------+------+------+
| 1 | 2 | 3 |
| 1 | 2 | 2323 |
| 1 | 323 | 21 |
| 9 | 9 | 9 |
+------+------+------+

4 rows in set (0.00 sec)



///取出所有a, b列不相同的行

mysql> select distinct a, b from ob;
+------+------+
| a | b |
+------+------+
| 1 | 2 |
| 1 | 323 |
| 9 | 9 |
+------+------+
3 rows in set (0.00 sec)



在数据库的设计中,如何实现Distinct操作呢?一般有两种基本思路:排序(Sort)法,哈希(Hash)法。

排序法将表格中的数据全部按照distinct指定的列为key进行排序,然后逐行迭代,每迭代出一行数据都与上一行数据根据key作对比,如果相同,则丢弃当前行继续迭代下一行,如果不同则输出。排序法带来的一个副作用就是数据输出按照key有序。mysql在某些情况下不是使用排序法,通过下面的输出可以观察到行并不是有序的:

mysql> select distinct a, b from ob;
+------+------+
| a | b |
+------+------+
| 1 | 2 |
| 1 | 323 |
| 9 | 9 |
| 0 | 0 |
+------+------+
4 rows in set (0.00 sec)

哈希法将表格中的数据全部按照distinct指定的列值为key作为hash key进行分桶,key相同的行自然就被区分出来了。

排序法在具体实现中会遇到这么一些问题:

1. 数据集超出了内存限制,如何排序?

2. 如何实现可以尽可能减少数据拷贝?

3. 如果已经有了Sort运算符,如何实现代码重用。


考虑一种理想实现,sort依次排序出最大,次大,较大,。。。等行,没一行输出后都跟前一行比较,如果key相等则丢弃,这样,sort完毕,distinct也做完了。堆排序可以较好地满足这一要求。但是,堆排序不支持外排,当数据集合超出内存限制时该方法将失效。




最后说个题外话,distinct跟groupby蛮像的,那么他们的区别又在哪里呢? 简单地说,distinct是一种很弱的groupby。详细见网上转载的一篇文章:


原文地址:http://lalaalisa.blogspot.com/2012/03/sql-distinct-vs-group-by.html

SQL語法 : DISTINCT vs GROUP BY

我使用的是SQLyog執行我的測試!! SQL語法的保留字~大小寫我在寫下列例子沒有很在意...

主要是為了情境所測出的心得~~如測試結果不同,請給我意見(pls leave comment)喔!!

CC~~ ^^

--------------------------------------------------------------------------------------------------------------
Table: member

id
name
email_address
11
Mary
22
Mary
33
John
44
Leo
55
Jane
55
Janny


--------------------------------------------------------------------------------------------------------------
Create Table member_distinct_by_name
Select Distinct name
From member
-------------------------------------------------
result:

Table: member_distinct_by_name


name
Mary
John
Leo
Jane

---------------------------------------------------------------------------------------------------------------
情境: 依據不重覆的 email_address,拉出想要的資料!

Create Table member_group_by_emailaddress
Select email_address, id
From member GROUP BY name


------------------------------------------------
result:

Table: member_group_by_ emailaddress

email_address
id
mary@gmail.com
11
mary@hotmail.com
22
john@gmail.com
33
leo@gmail.com
44
Jane@hotmail.com
55

----------------------------------------------------------------------------------------------------------------

Create Table member_distinct
Select Distinct email_address, name, id(只要有一欄位的data不一樣就會納入)
From member

---------------------------------------------------
result:

Table: member_distinct

ID
NAME
GENDER
11
Mary
22
Mary
33
John
44
Leo
55
Jane
55
Janny




/// 取出所有不同行
### SQLDISTINCT关键字的用法 #### DISTINCT关键字概述 在SQL(结构化查询语言)里,`DISTINCT`关键字被用来指示数据库只返回唯一不同的值。这有助于去除查询结果里的重复记录,从而确保每一行数据都是独一无二的[^1]。 #### 语法说明 为了实现这一功能,在编写`SELECT`语句时需紧随其后的列名之前放置`DISTINCT`关键字。需要注意的是,`DISTINCT`应位于所有待处理字段列表前而不是单独应用于某个特定字段内[^2]。 正确的语法形式如下所示: ```sql SELECT DISTINCT column1, column2,... FROM table_name; ``` 这里是一个具体的例子来展示如何利用`DISTINCT`获取某公司员工的不同薪资水平: ```sql SELECT DISTINCT salary FROM employees; ``` 此命令将会筛选出表`employees`内的`salaray`字段,并移除任何可能存在的冗余数值,最终呈现出一份不含重复项的结果清单[^3]。 对于更复杂的需求比如找出账号ID为1001所使用的不同渠道名称,可以通过下面的方式完成: ```sql SELECT account_name, channel_name FROM accounts_channels WHERE account_id = '1001' GROUP BY account_name, channel_name; -- 或者使用 DISTINCT 实现相同效果 -- SELECT DISTINCT account_name, channel_name FROM accounts_channels WHERE account_id = '1001'; ``` 上述两种方法均能达到目的——即获得由两个属性构成且无重复条目的表格;其中第二种方式更加直观简洁地表达了意图[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值