一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

mysql 執(zhí)行sql語句執(zhí)行問題

 印度阿三17 2019-03-06

 SQL是一套標(biāo)準(zhǔn),全稱結(jié)構(gòu)化查詢語言,是用來完成和數(shù)據(jù)庫之間的通信的編程語言,SQL語言是腳本語言,直接運(yùn)行在數(shù)據(jù)庫上。同時(shí),SQL語句與數(shù)據(jù)在數(shù)據(jù)庫上的存儲(chǔ)方式無關(guān),只是不同的數(shù)據(jù)庫對于同一條SQL語句的底層實(shí)現(xiàn)不同罷了,但結(jié)果相同。這有點(diǎn)類似于java中接口的作用,一個(gè)接口可以有不同的實(shí)現(xiàn)類,不同的實(shí)現(xiàn)類對于接口中方法的實(shí)現(xiàn)方式可以不同,結(jié)果可以相同。這里SQL語言的作用就類似于java中的接口,數(shù)據(jù)庫就類似于java中接口的實(shí)現(xiàn)類,SQL語句就類似于java接口中的方法。不同的是java中接口的不同實(shí)現(xiàn)類對于接口中方法的執(zhí)行結(jié)果可以相同,也可以不同,而不同的數(shù)據(jù)庫對于同一條SQL語句的執(zhí)行是相同的。(這里只是做一個(gè)類比,方便我們理解)

  一般情況下,大部分SQL語句在不同的數(shù)據(jù)庫上是通用的,但我們知道每個(gè)數(shù)據(jù)庫都有自己獨(dú)有的特性,像在MySql數(shù)據(jù)庫中,可以使用substr(取字符串),trim(去空格),ifnull(空值處理函數(shù)),還可以使用limit語句對數(shù)據(jù)庫表進(jìn)行截取,但這些都是oracle數(shù)據(jù)庫沒有的。(類比接口實(shí)現(xiàn)類中,實(shí)現(xiàn)類獨(dú)有的方法,而接口中沒有的)

  這里簡單介紹一下mysql數(shù)據(jù)庫,mysql數(shù)據(jù)庫是一款關(guān)系型數(shù)據(jù)庫,所謂關(guān)系型數(shù)據(jù)庫就是以二維表的形式存儲(chǔ)數(shù)據(jù),使用行和列方便我們對數(shù)據(jù)的增刪改查。

  這篇博客,我們以mysql數(shù)據(jù)庫為例,對一條sql語句的執(zhí)行流程進(jìn)行分析。(本篇博客不涉及到表連接)

  首先,創(chuàng)建一張student表,字段有自增主鍵id,學(xué)生姓名name,學(xué)科subject,成績grade

  建表語句:

復(fù)制代碼
DROP TABLE IF EXISTS student;
CREATE TABLE `student` (
  `id` int(5) NOT NULL AUTO_INCREMENT,
  `name` varchar(10) DEFAULT NULL,
  `subject` varchar(10) DEFAULT NULL,
  `grade` double(4,1) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=40 DEFAULT CHARSET=utf8;
復(fù)制代碼

  初始化數(shù)據(jù):

復(fù)制代碼
INSERT INTO student(`name`,`subject`,grade)VALUES('aom','語文',88);
INSERT INTO student(`name`,`subject`,grade)VALUES('aom','數(shù)學(xué)',99);
INSERT INTO student(`name`,`subject`,grade)VALUES('aom','外語',55);

INSERT INTO student(`name`,`subject`,grade)VALUES('jack','語文',67);
INSERT INTO student(`name`,`subject`,grade)VALUES('jack','數(shù)學(xué)',44);
INSERT INTO student(`name`,`subject`,grade)VALUES('jack','外語',55);

INSERT INTO student(`name`,`subject`,grade)VALUES('susan','語文',56);
INSERT INTO student(`name`,`subject`,grade)VALUES('susan','數(shù)學(xué)',35);
INSERT INTO student(`name`,`subject`,grade)VALUES('susan','外語',77);

INSERT INTO student(`name`,`subject`,grade)VALUES('alice','語文',88);
INSERT INTO student(`name`,`subject`,grade)VALUES('alice','數(shù)學(xué)',77);
INSERT INTO student(`name`,`subject`,grade)VALUES('alice','外語',100);

INSERT INTO student(`name`,`subject`,grade)VALUES('rajo','語文',33);
INSERT INTO student(`name`,`subject`,grade)VALUES('rajo','數(shù)學(xué)',55);
INSERT INTO student(`name`,`subject`,grade)VALUES('rajo','外語',55);
復(fù)制代碼

下面我們來看一下,數(shù)據(jù)在數(shù)據(jù)庫中的存儲(chǔ)形式。

 ?。▓D1.0)

現(xiàn)在針對這張student表中的數(shù)據(jù)提出一個(gè)問題:要求查詢出掛科數(shù)目多于兩門(包含兩門)的前兩名學(xué)生的姓名,如果掛科數(shù)目相同按學(xué)生姓名升序排列。

下面是這條查詢的sql語句

SELECT `name`,COUNT(`name`) AS num FROM student WHERE grade < 60 GROUP BY `name` HAVING num >= 2 ORDER BY num DESC,`name` ASC LIMIT 0,2;

執(zhí)行結(jié)果:

  圖(1.1)

以上這條sql語句基本上概括了單表查詢中所有要注意的點(diǎn),那么我們就以這條sql為例來分析一下一條語句的執(zhí)行流程。

1,一條查詢的sql語句先執(zhí)行的是?FROM student?負(fù)責(zé)把數(shù)據(jù)庫的表文件加載到內(nèi)存中去,如圖1.0中所示。(mysql數(shù)據(jù)庫在計(jì)算機(jī)上也是一個(gè)進(jìn)程,cpu會(huì)給該進(jìn)程分配一塊內(nèi)存空間,在計(jì)算機(jī)‘服務(wù)’中可以看到,該進(jìn)程的狀態(tài))

  圖(1.2)

2,WHERE grade?<?60,會(huì)把(圖1.0)所示表中的數(shù)據(jù)進(jìn)行過濾,取出符合條件的記錄行,生成一張臨時(shí)表,如下圖所示。

  圖(1.3)

?

3,GROUP?BY `name`會(huì)把圖(1.3)的臨時(shí)表切分成若干臨時(shí)表,我們用下圖來表示內(nèi)存中這個(gè)切分的過程。

????? ?? ?   ???

  圖(1.4)              圖(1.5)               圖(1.6)             ?圖(1.7)

4,SELECT?的執(zhí)行讀取規(guī)則分為sql語句中有無GROUP?BY兩種情況。

 ?。?)當(dāng)沒有GROUP?BY時(shí),SELECT?會(huì)根據(jù)后面的字段名稱對內(nèi)存中的一張臨時(shí)表整列讀取。

 ?。?)當(dāng)查詢sql中有GROUP?BY時(shí),會(huì)對內(nèi)存中的若干臨時(shí)表分別執(zhí)行SELECT,而且只取各臨時(shí)表中的第一條記錄,然后再形成新的臨時(shí)表。這就決定了查詢sql使用GROUP?BY的場景下,SELECT后面跟的一般是參與分組的字段和聚合函數(shù),否則查詢出的數(shù)據(jù)要是情況而定。另外聚合函數(shù)中的字段可以是表中的任意字段,需要注意的是聚合函數(shù)會(huì)自動(dòng)忽略空值。

  我們還是以本例中的查詢sql來分析,現(xiàn)在內(nèi)存中有四張被GROUP?BY `name`切分成的臨時(shí)表,我們分別取名為?tempTable1,tempTable2,tempTable3,tempTable4分別對應(yīng)圖(1.4)、圖(1.5)、圖(1.6),圖(1.7)下面寫四條"偽SQL"來說明這個(gè)查詢過程。

SELECT `name`,COUNT(`name`) AS num FROM tempTable1;
SELECT `name`,COUNT(`name`) AS num FROM tempTable2;
SELECT `name`,COUNT(`name`) AS num FROM tempTable3;
SELECT `name`,COUNT(`name`) AS num FROM tempTable4;

最后再次成新的臨時(shí)表,如下圖:

  圖(1.8)

5,HAVING num?>=?2對上圖所示臨時(shí)表中的數(shù)據(jù)再次過濾,與WHERE語句不同的是HAVING?用在GROUP?BY之后,WHERE是對FROM student從數(shù)據(jù)庫表文件加載到內(nèi)存中的原生數(shù)據(jù)過濾,而HAVING?是對SELECT?語句執(zhí)行之后的臨時(shí)表中的數(shù)據(jù)過濾,所以說column AS otherName ,otherName這樣的字段在WHERE后不能使用,但在HAVING?后可以使用。但HAVING的后使用的字段只能是SELECT?后的字段,SELECT后沒有的字段HAVING之后不能使用。HAVING num?>=?2語句執(zhí)行之后生成一張臨時(shí)表,如下:

?  圖(1.9)

6,ORDER?BY num?DESC,`name`?ASC對以上的臨時(shí)表按照num,name進(jìn)行排序。

7,LIMIT?0,2取排序后的前兩個(gè)。

以上就是一條sql的執(zhí)行過程,同時(shí)我們在書寫查詢sql的時(shí)候應(yīng)當(dāng)遵守以下順序。

SELECT XXX FROM XXX WHERE XXX GROUP BY XXX HAVING XXX ORDER BY XXX LIMIT XXX;

?

  最后說一點(diǎn),我們作為程序員,研究問題還是要仔細(xì)深入一點(diǎn)的。當(dāng)你對原理了解的有夠透徹,開發(fā)起來也就得心應(yīng)手了,很多開發(fā)中的問題和疑惑也就迎刃而解了,而且在面對其他問題的時(shí)候也可做到觸類旁通。當(dāng)然在開發(fā)中沒有太多的時(shí)間讓你去研究原理,開發(fā)中要以實(shí)現(xiàn)功能為前提,可等項(xiàng)目上線的后,你有大把的時(shí)間或者空余的時(shí)間,你大可去刨根問底,深入的去研究一項(xiàng)技術(shù),為覺得這對一名程序員的成長是很重要的事情。

?

來源:http://www./content-2-132151.html

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    区一区二区三中文字幕| 国产精品成人免费精品自在线观看| 国产精品成人又粗又长又爽| 草草视频福利在线观看| 最新69国产精品视频| 欧美三级精品在线观看| 好吊日视频这里都是精品| 少妇熟女亚洲色图av天堂| 成年午夜在线免费视频| 丁香六月婷婷基地伊人| 美女黄片大全在线观看| 伊人久久五月天综合网| 十八禁日本一区二区三区| 日本二区三区在线播放| 青青操在线视频精品视频| 日韩精品中文字幕在线视频| 欧美黑人在线一区二区| 免费亚洲黄色在线观看| 福利新区一区二区人口| 国产福利一区二区久久| 久久99这里只精品热在线| 久久精品亚洲欧美日韩| 欧美一区二区三区在线播放| 欧美日韩综合在线第一页| 伊人久久青草地综合婷婷| 91欧美亚洲精品在线观看| 国产精品制服丝袜美腿丝袜| 黄男女激情一区二区三区| 欧美日韩中黄片免费看| 久久福利视频在线观看| 91熟女大屁股偷偷对白| 中国美女草逼一级黄片视频| 久久99夜色精品噜噜亚洲av| 日本特黄特色大片免费观看| 国产亚洲精品岁国产微拍精品| 殴美女美女大码性淫生活在线播放| 日本午夜一本久久久综合| 国产高清精品福利私拍| 日本高清不卡在线一区| 不卡在线播放一区二区三区| 色婷婷视频免费在线观看|