前幾天參加了一個公司的面試,到了后面面試官出了一個SQL相關(guān)的題目:

創(chuàng)新互聯(lián)公司專注于嵐皋網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗。 熱誠為您提供嵐皋營銷型網(wǎng)站建設(shè),嵐皋網(wǎng)站制作、嵐皋網(wǎng)頁設(shè)計、嵐皋網(wǎng)站官網(wǎng)定制、微信小程序服務(wù),打造嵐皋網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供嵐皋網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。
數(shù)據(jù)的形式類似于以下這樣(表名為views):
當(dāng)時為了穩(wěn)妥起見,我的第一反應(yīng)是使用窗口函數(shù),
然后面試官問:“還有沒有什么簡便的方法么?”
很明顯他的意思是要用傳統(tǒng)的groupby來完成這個查詢,確實我之前的查詢又是用窗口函數(shù)又是加了distinct確實是復(fù)雜一些。
于是我用group by再寫了一遍。
看完我的查詢之后,面試官又問了一句:“可以不需要使用嵌套查詢嗎?”
當(dāng)時我的回答是”應(yīng)該不行,如果不使用嵌套而直接在group by后面加having的話sql會報錯,就和where如果使用別名查詢就會報錯一樣“
后面面試完想了一下,發(fā)現(xiàn)自己當(dāng)時回答得不好,不是正確的但也不完全錯,不是正確的原因是按照sql的規(guī)則having后面是可以拿聚合函數(shù)做判斷的,但是不完全錯的原因是如果having用的是像我之前設(shè)置的別名來判斷的話,確實是會出錯的。(雖然mysql在5.6之后基于sql的規(guī)則對group by進行拓展,支持這種寫法。但在其它sql上面用別名having還是不行的)
我們可以從SQL運行時各部分的執(zhí)行順序來進行分析,當(dāng)我們選擇執(zhí)行一個SQL語句的時候,它會按照以下的順序來進行操作,
這個執(zhí)行順序的設(shè)計是很巧妙的,我說一下我自己對于上述順序的理解,
1. FROM
顧名思義,當(dāng)執(zhí)行查詢語句的時候,首先需要知道的是它需要哪些表,正如我們?nèi)ヒ粋€地方需要知道它的具體位置一樣。如果需要多個表的話在這一部分也需要按照一定的順序進行表的join操作。
2. WHERE
當(dāng)確定我們需要讀取哪一張表(或者多張表)的數(shù)據(jù)之后,我們就需要進行where的filter操作,根據(jù)filter盡量減少讀取的數(shù)據(jù)數(shù)量。
那么問題來了,為什么where的優(yōu)先級要比group by,having, select之類的要高呢?
第一個原因是可以減少不必要的查詢量,加快執(zhí)行語句的速度,類似于Apache Spark在對查詢語句進行邏輯優(yōu)化時需要用到的謂詞下推類似的道理。舉個栗子,比如我們可能需要userid從100到300的用戶對于某一個頁面的瀏覽次數(shù),那么如果先執(zhí)行g(shù)roup by再執(zhí)行where的話,userid小于100的用戶的數(shù)據(jù)也會被匯總進去,但實際上這些部分的數(shù)據(jù)是完全不需要的,計算它們完全是浪費系統(tǒng)資源(而且group by操作本身就是很耗資源的操作)
3. GROUP BY
在完成where操作的過濾之后,如果語句中有g(shù)roup by的話則會對過濾后的數(shù)據(jù)進行聚合操作,聚合操作是多對一的轉(zhuǎn)換,因此在聚合操作過后,除了用于group by的字段之外,其它字段的原始數(shù)據(jù)將會丟失,只能得到它們相應(yīng)的聚合結(jié)果(比如sum(), avg()這樣)
在完成聚合操作之后,參與group by的字段以及其它字段對應(yīng)的聚合值已經(jīng)處于已知狀態(tài),后續(xù)的操作可以直接使用它們。
4. HAVING
HAVING操作主要做的是對group by之后的分組結(jié)果進行過濾,可以根據(jù)參與group by的字段進行過濾,也可以根據(jù)其它字段的聚合值進行過濾。(因為聚合值在這里已經(jīng)算是已知數(shù)據(jù))因此這里是可以拿聚合函數(shù)做判斷的,比如最開始的那個查詢的例子,可以直接寫成以下的形式,
HAVING并不是一定要和group by成對出現(xiàn)的,它也可以單獨存在,在沒有g(shù)roup by的時候,此時默認(rèn)只有一個組,但是需要注意的是這時having里面參與過濾的字段需要在select里面存在,不然having會不知道這是分組里面的內(nèi)容而導(dǎo)致報錯。
5. SELECT
選取結(jié)果集中相對應(yīng)的字段,在select中為字段設(shè)置的別名在此階段及之后的操作中生效。
6. DISTINCT
去重操作,放在select之后有個原因是去重操作是要根據(jù)select里面所選字段來進行的。
7. ORDER BY
對得到的結(jié)果按照特定字段順序進行排列,這里可以使用別名
8. LIMIT
設(shè)置顯示結(jié)果集中的幾條數(shù)據(jù)
通過分析MySQL中各部分的執(zhí)行順序,我們就不難理解為什么where不能有別名,而having可以用聚合函數(shù)來判斷的原因,而且借此機會重新溫習(xí)一遍SQL各部分對應(yīng)的功能,加深理解,可以說是一舉兩得。
MySQL的排序,使用order by來實現(xiàn)。
order by id asc,表示用id升序排列
order by id desc,表示用id降序排列
當(dāng)需要用多個字段排序時,order by cdate desc,id asc,表示先用cdate降序排列,cdate相同的再用id升序排列
ORDER BY 默認(rèn)按升序排列,因此 ASC (升序)子句是可選的。
另外,還可以按降序排列,為此可以使用 DESC(降序)。
ORDER BY 子句中還可以用數(shù)字來表示對應(yīng)的列 3 對應(yīng)于 SELECT 中指定的第 3 列,即工資。
按從左到右的順序依次根據(jù) ORDER BY 子句中指定的列進行排序。
指定用于排序的列時,如果使用的是 SELECT 子句中列的數(shù)字位置,那么指定的數(shù)字不能超過 SELECT 子句中指定的列數(shù)。( 不能超出索引 )
通常,可以按 SELECT 子句中未指定的列進行排序,但必須指定列名。然而,如果在查詢中使用了GROUP BY 或 DISTINCT 子句,就不能按SELECT 子句中未指定的列進行排序。
要求:顯示部門編號為 10 的員工的姓名、職位和薪水,并根據(jù)薪水按從低到高的順序排列想獲得上面這樣的數(shù)據(jù)結(jié)果
如果想對表中多個字段進行不同的排列如工資表按照升序排列,年齡按照降序排列
可以再ORDER之后用逗號隔開不同排列的字段
SQL的核心要點是從數(shù)據(jù)存儲格式獲取應(yīng)用。總應(yīng)指定檢索數(shù)據(jù)的順序。在下面的第1條語句中,以 col_name1、col_name2、col_name3順序返回列;在第2條語句中,以col_name1、col_name3、 col_name2順序返回列: MySQL SELECT col_name1, col_name2, col_name3 FROM tbl_name; mysql SELECT col_name1, col_name3, col_name2 FROM tbl_name; 如果決定更改表列的順序,可執(zhí)行下述操作: 用具有新順序的列創(chuàng)建新表。 執(zhí)行該語句: mysql INSERT INTO new_table - SELECT columns-in-new-order FROM old_table; 撤銷或重命名old_table。
前幾天工作上遇到一個問題,在mysql數(shù)據(jù)查詢的時候,使用的是in條件,而結(jié)果需要根據(jù)in來進行排序,當(dāng)時嘗試了幾次都沒成功,后來在度娘的幫助下,找到了解決辦法:
select * from table_name where id in (6,2,1,10,5,7..)
查詢的結(jié)果和in中的順序并不一致,也就是說在批量查詢時,mysql的查詢并不是按照in中的值得順序來查詢的。那怎么才能保證和in查詢中的順序相同呢?
查詢了資料發(fā)現(xiàn)有兩種方式可以對in查詢的結(jié)果進行排序。一種是order by find_in_set,另外一種是order by substring_index
1、select * from table_name where id in (6,2,1,10,5,7..) order by find_in_set(id,'6,2,1,10,5,7');
2、select * from table_name where id in (6,2,1,10,5,7..)?order by substring_index('6,2,1,10,5,7',id,1);
SQL的要點是中抽象應(yīng)用程序以避免數(shù)據(jù)存儲格式。你應(yīng)該總是以你想要檢索數(shù)據(jù)的意愿指定順序。例如:
SELECT col_name1, col_name2, col_name3 FROM tbl_name;
將以col_name1、col_name2、col_name3的順序返回列,而:
SELECT col_name1, col_name3, col_name2 FROM tbl_name;
將以col_name1、col_name3、col_name2的順序返回列。
在一個應(yīng)用程序中,你應(yīng)該決不基于他們的位置使用SELECT * 檢索列,因為被返回的列的順序永遠不能保證;對你的數(shù)據(jù)庫的一個簡單改變可能導(dǎo)致你的應(yīng)用程序相當(dāng)有戲劇性地失敗。
不管怎樣,如果你想要改變列的順序,你可以這樣做:
以正確的列順序創(chuàng)建一張新表。
執(zhí)行INSERT INTO new_table SELECT fields-in-new_table-order FROM old_table.
刪除或改名old_table。
ALTER TABLE new_table RENAME old_table。
文章標(biāo)題:mysql怎么設(shè)置順序,mysql字段順序調(diào)整
鏈接URL:http://chinadenli.net/article17/dseccgj.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)網(wǎng)站建設(shè)、外貿(mào)建站、微信公眾號、手機網(wǎng)站建設(shè)、靜態(tài)網(wǎng)站、網(wǎng)站策劃
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)