1. 程式人生 > >資料庫查詢去重group by和distinct的理解

資料庫查詢去重group by和distinct的理解

前言

在使用mysql時,有時需要查詢出某個欄位不重複的記錄,雖然mysql提供 有distinct這個關鍵字來過濾掉多餘的重複記錄只保留一條,但往往只用它來返回不重複記錄的條數,而不是用它來返回不重記錄的所有值。其原因是 distinct只能返回它的目標欄位,而無法返回其它欄位,而group by也可能分組的方式來去掉一些重複行,直接看例子.資料庫:

id name
1 a
2 b
3 c
4 c
5 b

庫結構大概這樣,這只是一個簡單的例子,實際情況會複雜得多。

比如我想用一條語句查詢得到name不重複的所有資料,那就必須使用distinct去掉多餘的重複記錄。

select distinct name from table

得到的結果是:
   name
   a
   b
   c

好像達到效果了,可是,我想要得到的是id值呢?改一下查詢語句吧:

select distinct name, id from table

結果會是:

id name
1 a
2 b
3 c
4 c
5 b

distinct怎麼沒起作用?作用是起了的,不過他同時作用了兩個欄位,也就是必須得id與name都相同的才會被排除。。。。。。。

我們再改改查詢語句:

select id, distinct name from table

很遺憾,除了錯誤資訊你什麼也得不到,distinct必須放在開頭。難到不能把distinct放到where條件裡?能,照樣報錯。。。。。。。

很麻煩吧?確實,費盡心思都沒能解決這個問題。

用count函式一試,成功,我。。。。。。。想哭啊,費了這麼多工夫。。。。。。。。原來就這麼簡單。。。。。。

現在將完整語句放出:

select *, count(distinct name) from table group by name

結果:

id name count(distinct name)
1 a 1
2 b 1
3 c 1

最後一項是多餘的,不用管就行了,目的達到。。。。。

唉,原來mysql這麼笨,輕輕一下就把他騙過去了,鬱悶也就我吧(對了,還有容容那傢伙),現在拿出來希望大家不要被這問題折騰。
哦,對,再順便說一句,group by

group by 用法解析
group by語法可以根據給定資料列的每個成員對查詢結果進行分組統計,最終得到一個分組彙總表。
SELECT子句中的列名必須為分組列或列函式。列函式對於GROUP BY子句定義的每個組各返回一個結果。
某個員工資訊表結構和資料如下:

  id  name  dept  salary  edlevel  hiredate 
      1 張三 開發部 2000 3 2009-10-11
      2 李四 開發部 2500 3 2009-10-01
      3 王五 設計部 2600 5 2010-10-02
      4 王六 設計部 2300 4 2010-10-03
      5 馬七 設計部 2100 4 2010-10-06
      6 趙八 銷售部 3000 5 2010-10-05
      7 錢九 銷售部 3100 7 2010-10-07
      8 孫十 銷售部 3500 7 2010-10-06 

例如,我想列出每個部門最高薪水的結果,sql語句如下:
SELECT DEPT, MAX(SALARY) AS MAXIMUM
FROM STAFF
GROUP BY DEPT
查詢結果如下:
DEPT MAXIMUM
開發部 2500
設計部 2600
銷售部 3500
解釋一下這個結果:
1、滿足“SELECT子句中的列名必須為分組列或列函式”,因為SELECT有GROUP BY DEPT中包含的列DEPT。
2、“列函式對於GROUP BY子句定義的每個組各返回一個結果”,根據部門分組,對每個部門返回一個結果,就是每個部門的最高薪水。
注意:計算的是每個部門(由 GROUP BY 子句定義的組)而不是整個公司的 MAX(SALARY)。
例如,查詢每個部門的總的薪水數

SELECT DEPT, sum( SALARY ) AS total
FROM STAFF
GROUP BY DEPT
查詢結果如下:
DEPT  total 
開發部 4500
設計部 7000
銷售部 9600

將 WHERE 子句與 GROUP BY 子句一起使用
分組查詢可以在形成組和計算列函式之前具有消除非限定行的標準 WHERE 子句。必須在GROUP BY 子句之前指定 WHERE 子句。
例如,查詢公司2010年入職的各個部門每個級別裡的最高薪水
SELECT DEPT, EDLEVEL, MAX( SALARY ) AS MAXIMUM
FROM staff
WHERE HIREDATE > ‘2010-01-01’
GROUP BY DEPT, EDLEVEL
ORDER BY DEPT, EDLEVEL
查詢結果如下:
DEPT EDLEVEL MAXIMUM
設計部 4 2300
設計部 5 2600
銷售部 5 3000
銷售部 7 3500
注意:在SELECT語句中指定的每個列名也在GROUP BY子句中提到。未在這兩個地方提到的列名將產生錯誤。
GROUP BY子句對DEPT和EDLEVEL的每個唯一組合各返回一行。
在GROUP BY子句之後使用HAVING子句
可應用限定條件進行分組,以便系統僅對滿足條件的組返回結果。為此,在GROUP BY子句後面包含一個HAVING子句。HAVING子句可包含一個或多個用AND和OR連線的謂詞。每個謂詞將組特性(如AVG(SALARY))與下列之一進行比較:
例如:尋找僱員數超過2個的部門的最高和最低薪水:
SELECT DEPT, MAX( SALARY ) AS MAXIMUM, MIN( SALARY ) AS MINIMUM
FROM staff
GROUP BY DEPT
HAVING COUNT( * ) >2
ORDER BY DEPT
查詢結果如下:
DEPT MAXIMUM MINIMUM
設計部 2600 2100
銷售部 3500 3000
例如:尋找僱員平均工資大於3000的部門的最高和最低薪水:
SELECT DEPT, MAX( SALARY ) AS MAXIMUM, MIN( SALARY ) AS MINIMUM
FROM staff
GROUP BY DEPT
HAVING AVG( SALARY ) >3000
ORDER BY DEPT
查詢結果如下:
DEPT MAXIMUM MINIMUM
銷售部 3500 3000