mysql中exists的詳細說明

以前碰到了一道題,下面簡要說明一下:mysql

表結構以下:sql

CREATE TABLE `testa` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`cid` int(11) DEFAULT NULL comment '產品ID',
`uid` int(11) DEFAULT NULL comment '用戶ID',
`buytime` int(11) DEFAULT NULL comment '購買時間',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf-8;數據庫

採用以下sql,隨機插入一批測試數據:測試

INSERT into testa (cid,uid,buytime) values (rand()*5,rand()*5,rand()*10000);ui

說明:rand()返回0到1的隨機小數,例如:0.4578285091163856,因爲上表幾個字段均爲int類型在數據庫存儲時會自動進行四捨五入取整存儲。spa

好了,下面進入正題:在該表內查出每一個產品最先購買該產品的三個客戶ID。描述好簡單的一道題,當時難住了博主,通過多方查詢資料,終於搞到了正確答案:.net

select * from testa as a where NOT EXISTS (select * from testa as b where a.cid = b.cid and a.buytime < b.buytime group by b.cid HAVING count(*) > 2);blog

這裏最關鍵的幾個個關鍵方法,exists 、 group by 和 having;utf-8

按照單個理解:exists爲判斷括號裏面表達式返回結果是否爲真,返回真則將當前主表的數據取出,不然放棄取出該結果(博主寫該片文章時只瞭解這麼多,還未深刻)NOT EXISTS和EXISTS做用互斥,不作過多解釋。ci

group by 不用過多解釋,即將當前查詢結果按照某個字段進行分組,去重。

having 的做用是將mysql執行完畢的最終結果進行二次處理的方法。

先說一下剛拿到這條sql的時候百思不得其解,認爲exists應該和in的功能相似,先執行括號裏面的方法,獲得所有結果以後返回給主表進行二次查詢,可是group by 以後的數據條件根本不能知足,最終仍是求助於萬能的因特奈特,終於明白該條sql得處理過程了,以下說明 :

由於group by 是要在where條件以後纔會執行,因此會先執行子查詢 中a表和b表的where關聯查詢,執行完where條件以後返回true,因此exists會執行爲真。

這裏說明一下exists執行過程:首先在a表拿第一條數據和b表的全部數據進行關聯,獲得全部大於當前a表查詢數據的購買時間的b表數據,按照b表的產品進行分組,而且count(*)會記住當前結果獲取到的行數,雖然having這時候還未生效;而後執行a表第二條數據,依次循環執行完a表全部數據以後,經過having進行結果整理,將全部查詢行數大於2的所有拋棄(NOT EXISTS),獲得最終結果。

說明:由於咱們要取最先的三個客戶,因此購買時間越小排名越高,而且當執行第一早客戶的時候,a.buytime < b.buytime該條件count(*) 返回結果爲0。

從新整理後sql能夠這麼寫:select * from testa as b where EXISTS (select * from testa as c where c.cid = b.cid and b.buytime <= c.buytime group by c.cid HAVING count(*) <= 3);

 

借閱文章地址:

http://blog.csdn.net/qsyzb/article/details/12523051

http://fucheng.blog.51cto.com/2404495/1575693

相關文章
相關標籤/搜索