產品操作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.


分享到:


相關文章: