在 MySQL 查詢中,可能會包含重復值。這并不成問題,不過,有時您也許希望僅僅列出不同(distinct)的值。
關鍵詞 DISTINCT 用于返回唯一不同的值,就是去重啦。用法也很簡單:
| SELECT DISTINCT * FROM tableName |
DISTINCT 這個關鍵字來過濾掉多余的重復記錄只保留一條。
另外,如果要對某個字段去重,可以試下:
| SELECT *, COUNT(DISTINCT nowamagic) FROM table GROUP BY nowamagic |
這個用法,MySQL的版本不能太低。
在編寫查詢之前,我們甚至應該對過濾條件進行排序,真正高效的條件(可能有多個,涉到同的表)是查詢的主要驅動力,低效條件只起輔助作用。那么定義高效過濾條件的準則是什呢?首先,要看過濾條件能否盡快減少必須處理的數據量。所以,我們必須倍加關注條件的寫方式。
假設有四個表: customers 、 orders 、 orderdetail 、 articles ,現在假設 SQL 要處理的問題是:找出最近六個月內居住在 Gotham 市、訂購了蝙蝠車的所有客戶。當然,編寫這個查詢有多種方法, ANSI SQL 的推崇者可能寫出下列語句:
| select distinct c.custnamefrom customers cjoin orders oon o.custid = c.custidjoin orderdetail odon od.ordid = o.ordidjoin articles aon a.artid = od.artidwhere c.city = 'GOTHAM'and a.artname = 'BATMOBILE'and o.ordered >= somefunc |
其中, somefunc 是個函數,返回距今六個月前的具體日期。注意上面用了 distinct ,因為考慮到某個客戶可以是大買家,最近訂購了好幾臺蝙蝠車。
暫不考慮優化器將如何改寫此查詢,我們先看一下這段代碼的含義。首先,來自 customers 表的數據應只保留城市名為 Gotham 的記錄。接著,搜索 orders 表,這意味著 custid 字段最好有索引,否則只有通過排序、合并或掃描 orders 表建立一個哈希表才能保證查詢速度。對 orders 表 ,還要針對訂單日期進行過濾:如果優化器比較聰明,它會在連接( join )前先過濾掉一些數據,從而減少后面要處理的數據量;不太聰明的優化器則可能會先做連接,再作過濾,這時在連接中指定過濾條件利于提高性能,例如:
| join orders oon o.custid = c.custidand a.ordered >= somefunc |
注意,如果是:
| left outer join orders o ono.custid = c.custidand a.ordered >= somefunc |
此處關于left表的篩選條件將失效,因為是左外連接,左表的所有列都將出現在這次連接結果集中)。
即使過濾條件與連接( join )無關,優化器也會受到過濾條件的影響。例如,若 orderdetail 的主鍵為( ordid, artid ),即 ordid 為索引的第一個屬性,那么我們可以利用索引找到與訂單相關的記錄。但如果主鍵是( artid, ordid )就太不幸了(注意,就關系理論而言 ,無論哪個版本都是完全一樣),此時的訪問效率比( ordid, artid )作為索引時要差,甚至一些數據庫產品無法使用該索引(注 3 ),唯一的希望就是在ordid 上加獨立索引了。
新聞熱點
疑難解答