1. 程式人生 > 其它 >MySQL中特別實用的幾種SQL語句送給大家,絕了

MySQL中特別實用的幾種SQL語句送給大家,絕了

MySQL中特別實用的幾種SQL語句送給大家,絕了

-- 使用者首次新增

INSERT IGNORE INTO users_info (id, username, sex, age ,balance, create_time) 

   VALUES (null, 'chenhaha', '男', 12, 0, '2020-06-11 20:00:20');



-- 二次新增,直接忽略

INSERT IGNORE INTO users_info (id, username, sex, age ,balance, create_time) 

   VALUES (null, 'chenhaha', '男', 12, 0, '2020-06-11 21:00:20');

若username='chenhaha'的記錄不存在,INSERT語句將插入新記錄,否則,不執行任何操作。

4.SQL中的if-else判斷語句


眾所周知,if-else判斷在任何地方都很有用,在SQL語句中,"CASE WHEN ... THEN ... ELSE ... END"語句可以用在增刪改查各類語句中。

  • 給個情景:婦女節大回饋,2020年註冊的新使用者,所有成年女性賬號送10元紅包,其他使用者送5元紅包,自動充值。

示例語句如下:


-- 送紅包語句

UPDATE users_info u 

    SET u.balance = CASE WHEN u.sex ='女' and u.age > 18 THEN u.balance + 10 

                         ELSE u.balance + 5 end 

                         WHERE u.create_time >= '2020-01-01'

  • 情景2:有個學生高考分數表,需要將等級列出來,650分以上是重點大學,600-650是一本,500-600分是二本,400-500是三本,400以下大專;

原測試資料如下:

查詢語句:


SELECT *,case when total_score >= 650 ?THEN '重點大學'?

? ? ? ? ? ? ? when total_score >= 600 and total_score <650 THEN '一本'

? ? ? ? ? ? ? when total_score >= 500 and total_score <600 THEN '二本'

? ? ? ? ? ? ? when total_score >= 400 and total_score <500 THEN '三本' ? ? ? ?

? ? ? ? ? ? ? else '大專' end as status_student?

? ? ? ? ? ? ? from student_score;

5.指定資料快照或備份


如果想要對一個表進行快照,即複製一份當前表的資料到一個新表,可以結合CREATE TABLE和SELECT:


-- 對class_id=1(一班)的記錄進行快照,並存儲為新表students_of_class1:

CREATE TABLE students_of_class1 SELECT * FROM student WHERE class_id=1;

新建立的表結構和SELECT使用的表結構完全一致。

6.寫入查詢結果集


如果查詢結果集需要寫入到表中,可以結合INSERT和SELECT,將SELECT語句的結果集直接插入到指定表中。

例如,建立一個統計成績的表statistics,記錄各班的平均成績:


CREATE TABLE statistics (

? ? id BIGINT NOT NULL AUTO_INCREMENT,

? ? class_id BIGINT NOT NULL,

? ? average DOUBLE NOT NULL,

? ? PRIMARY KEY (id)

);

然後,我們就可以用一條語句寫入各班的平均成績:


INSERT INTO statistics (class_id, average) SELECT class_id, AVG(score) FROM students GROUP BY class_id;

確保INSERT語句的列和SELECT語句的列能一一對應,就可以在statistics表中直接儲存查詢的結果:


SELECT * FROM statistics;

+----+----------+--------------+

| id | class_id | average ? ? ?|

+----+----------+--------------+

| ?1 | ? ? ? ?1 | ? ? ? ?475.5 |

| ?2 | ? ? ? ?2 | 473.33333333 |

| ?3 | ? ? ? ?3 | 488.66666666 |

+----+----------+--------------+

3 rows in set (0.00 sec)




  

7.強制使用指定索引

-------------



在查詢的時候,資料庫系統會自動分析查詢語句,並選擇一個最合適的索引。但是很多時候,資料庫系統的查詢優化器並不一定總是能使用最優索引。如果我們知道如何選擇索引,可以使用FORCE INDEX強制查詢使用指定的索引。例如:



SELECT * FROM students FORCE INDEX (idx_class_id) WHERE class_id = 1 ORDER BY id DESC;




指定索引的前提是索引idx\_class\_id必須存在。  

?



心得體會:

=====



? ? ? ?記得那一年,我還是個孩子,記得第一個需求是做個統計介面,查詢近兩小時每隔5分鐘為一時間段的網站訪問量,JSONArray中一共返回24個值,當時菜啊,寫了個介面迴圈二十四遍,傳送24條SQL去查(捂臉),由於那個介面,被技術經理嘲諷~~表示他寫的SQL比我吃的米都多。雖然我們山東人基本不吃米飯,但我還是羞愧不已。。



? ? ? ?然後經理通過呼叫一個dateTime函式分組查詢處理一下,就ok了,效率是我的幾十倍吧。從那時起,我就定下目標,深入MySQL學習,日後爭取嘲諷回去~~~



? ? ? ?筒子們,MySQL路漫漫,其修遠兮。永遠不要眼高手低,一起加油,希望本文能對你有所幫助。



\-------------------------------------------------------------?華麗的分割線 ---------------------------------------------------------



(續)評論區問題反饋

==========



? ? ? ? 這一週有好幾個朋友在評論區評論或私信我,問我當年那條SQL是咋寫的,經理是咋寫的。。看大家對知識的熱情這麼高,我必須得開源一下了,在這貼出來當時的SQL。有個點宣告,專案資料庫在內網不好測試,我就模擬了一張表來給大家統計一下吧。



? ? ? ? **需求回顧:時間就'2020-01-14 00:00:00' -?'2020-01-15 00:00:00' 為準,統計當天以每10分鐘為間隔的分組資料。**



@當年經理的SQL

---------



其中時間根據需求自行修改,由於我只生成了一天的測試資料,我就以此為例。



SELECT DATE_FORMAT(p.createTime, '%H') as date_str,count(*) as count

from data_timing p

where DATE_FORMAT(p.createTime, '%Y-%m-%d %H:%i:%S') >= DATE_FORMAT('2020-01-14 00:00:00', '%Y-%m-%d %H:%i:%S')

    AND DATE_FORMAT(p.createTime, '%Y-%m-%d %H:%i:%S') < DATE_FORMAT('2020-01-15 00:00:00', '%Y-%m-%d %H:%i:%S')

	GROUP BY HOUR(p.createTime)



經理這條SQL查詢的結果如下,基本保留了當年原版~~這條的意思是取“2020-01-14”這天24小時每小時的count。當時我很有啟發,也很有感覺,發現SQL還能這麼玩兒。完事兒寫完他說就要撤了,說要去接孩子。我說:“大佬,咱別吃飯吃一半兒啊,再給我來一下子唄”。



![](https://img-blog.csdnimg.cn/20200618150421257.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5MzkwNTQ1,size_16,color_FFFFFF,t_70)



@修改後最終版SQL

----------



然後經過我後續修改SQL如下:



SELECT concat( date_format( p.createTime, '%Y-%m-%d %H:' ) , floor( date_format( p.createTime, '%i' ) /10 )*10 ) as date_str

, count(*) as count from data_timing p

where DATE_FORMAT(p.createTime, '%Y-%m-%d %H:%i:%S') < DATE_FORMAT('2020-01-15 00:00:00', '%Y-%m-%d %H:%i:%S')

    AND DATE_FORMAT(p.createTime, '%Y-%m-%d %H:%i:%S') >= DATE_FORMAT('2020-01-14 00:00:00', '%Y-%m-%d %H:%i:%S')

    GROUP BY  concat( date_format( p.createTime, '%Y-%m-%d %H:' ) , floor( date_format( p.createTime, '%i' ) /10 )) 



乍一看是不是還挺複雜,並不是多複雜,只是其中幾個函式內容比較多。。比如concat()裡的那一堆,以及date\_format那些。先看結果吧。後面跟各位說一下查詢原理:



![](https://img-blog.csdnimg.cn/20200618152941108.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5MzkwNTQ1,size_16,color_FFFFFF,t_70)



@最終版SQL原理

---------



如上所述,是每隔10分鐘為一個時間段,當時只能想到了以每分鐘為時間段分組的SQL,如下。



SELECT concat( date_format( p.createTime, '%Y-%m-%d %H:' ) , floor( date_format( p.createTime, '%i' ) )) as date_str

, count(*) as count from data_timing p

	where DATE_FORMAT(p.createTime, '%Y-%m-%d %H:%i:%S') < DATE_FORMAT('2020-01-15 00:00:00', '%Y-%m-%d %H:%i:%S')

	AND DATE_FORMAT(p.createTime, '%Y-%m-%d %H:%i:%S') >= DATE_FORMAT('2020-01-14 00:00:00', '%Y-%m-%d %H:%i:%S')

	GROUP BY MINUTE(p.createTime)



查詢結果:


# 最後

**[送大家一個小福利,點選領取Java全套進階資料](https://gitee.com/vip204888/java-p7)**

![](https://upload-images.jianshu.io/upload_images/22932333-22b644c2288a5af8?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![](https://upload-images.jianshu.io/upload_images/22932333-749f3b631b79a579?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![](https://upload-images.jianshu.io/upload_images/22932333-e7f2af0656eab08e?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)