mysql常見sql語句練習
文章目錄
1. Mysql基本語句複習
1.1資料庫建庫操作
這一章會把基本的mysql語句進行復習
開啟Sqlyog,新建一個數據庫
1.2建表操作
新建兩張學習興趣班級表:唱歌、跳舞
CREATE TABLE sing(
s_num VARCHAR(5) NOT NULL UNIQUE COMMENT '身份證號,這兒為了方便以5位算' ,
s_beginDate DATE COMMENT '入班時間'
#指定儲存引擎為INNODB(這個在優化的時候會學習)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
CREATE TABLE dance(
d_num VARCHAR(5) NOT NULL UNIQUE COMMENT '身份證號,這兒為了方便以5位算',
d_beginDate DATE COMMENT '入班時間',
d_level TINYINT(1) COMMENT '0初級,1中級,2高階'
)ENGINE=INNODB DEFAULT CHARSET=utf8;
刪除表語句:(不演示了)
- drop table xxxx
- truncate table xxx
三者區別(加上delete三個,這是考點需要掌握):
drop:刪除表所有資料與表的資料結構,也就是表直接不存在了(無法回滾)
truncate: 會清空表中所有的資料,速度快,不可回滾;實質是刪除整張表包括資料再重新建立表(一旦提交不可回滾)
當然,涉及到刪除資料delete語句也是刪除資料,這兒就一起說了delete from xxx
delete: 逐行刪除資料,每步刪除都是有日誌記錄的,可以回滾資料;實質是逐行刪除表中的資料
總結:
速度:一般來說: drop> truncate > delete
安全性:小心使用 drop 和 truncate,尤其沒有備份的時候.否則哭都來不及
使用上,想刪除部分資料行用 delete,注意帶上where子句. 回滾段要足夠大.
想刪除表,當然用 drop;想保留表而將所有資料刪除,如果和事務無關,用truncate即可。如果和事務有關,用delete
1.3基本語句
條件查詢:**select * from table1 where 範圍
**插入:**insert into table1(field1,field2) values(value1,value2)
**刪除:**delete from table1 where 範圍
更新:update table1 set field1=value1 where 範圍
**查詢:select * from table1 where field1 like ’%value1%’
排序:select * from table1 order by field1,field2 [desc]
總數:select count(1) as totalcount from table1
求和:select sum(field1) as sumvalue from table1
平均:select avg(field1) as avgvalue from table1
最大:select max(field1) as maxvalue from table1
最小:select min(field1) as minvalue from table1
去重: select distinct field1 as minvalue from table1
distinct a,b,c,d abcd全部相同才是重複的
注:如果是distinct 多列 是以多列一起判斷是否重複
分組: select * from table1 group by xxx
group by a,b,c,d abcd全部相同才是一組
注:如果是分組 多列 是以多列一起判斷是否相同分組
自己練習!!!
1.4列操作(重點)
可以看到在上面的sing興趣班,對應的表中欄位少了,入班時間與等級兩個欄位,現在加入:
· 新增列語句:alter table 表名 add column 列名 varchar(30);
在sing表增加s_level列:
ALTER TABLE sing ADD COLUMN s_level TINYINT(1);
刪除列:alter table 表名 drop column 列名;
修改列名MySQL: alter table 表名 change 原名 新名 int;
修改列型別:alter table 表 modify name varchar(22);
這兒只演示了增加列,大家需要記住語句,筆試中可能會遇到
1.5join操作(重點)
為了方便測試,我們在兩張表中加入如下資料
#增加測試資料 唱歌班級
INSERT INTO sing(s_num,s_beginDate,s_level) VALUES
('10001','2000-01-01',1),
('10002','2001-01-01',2),
('10003','2002-01-01',3),
('10004','2003-01-01',3)
#增加測試資料 跳舞班級
INSERT INTO dance(d_num,d_beginDate,d_level) VALUES
('10003','2000-01-01',1),
('10004','2001-01-01',2),
('10005','2002-01-01',3),
('10006','2003-01-01',3)
1 inner join或者 join
查詢同時參加了兩個興趣班的同學的身份證號
身份證號就是連結條件
2 left join
查詢sing班級全體同學的身份證號及在dance班的等級
分析:sing全體同學,那麼沒有參加dance班也需要查出來
3 right join
查詢sing班級全體同學的身份證號及在dance班的等級
分析:sing全體同學,那麼沒有參加dance班也需要查出來
上題類似,用right join 只需要把sing表移到右邊即可
4…查詢只參加了sing興趣班的同學的身份證號碼
5.查詢兩個班所有學生的身份證號碼
注:union 用法 請檢視
http://www.w3school.com.cn/sql/sql_union.asp
說明:Oracle資料庫支援full join,mysql是不支援full join的
練習1:(重點)
查詢只選了一個興趣班學生的身份證號碼
答案見sql附件最後:
#查詢只選了一個興趣班學生的身份證號碼 3.4參加兩個班
SELECT s_num FROM sing LEFT JOIN dance ON s_num=d_num WHERE d_num IS NULL
UNION
SELECT d_num FROM sing RIGHT JOIN dance ON s_num=d_num WHERE s_num IS NULL
子查詢方式
select s_num from sing where s_num not in(select d_num from dance)
UNION
select d_num from dance where d_num not in(select s_num from sing)
1.6case when then else end(重點)
oracle:
select t.id,
t.name,
t.age,
decode(t.sex, '1', '男生', '2', '女生', '其他') as sex
from STUDENT2 t
case :指定欄位
when:當什麼條件
then:滿足上面的條件 就幹什麼
else:前面的條件都不滿足
end:結束語
直接看題來解釋吧
1.6.1查詢興趣班sing表,要求欄位level,初中高替換123
也可以寫成如下格式
1.6.2.統計sing班級 初中高等級的個數,按如下結果顯示
練習2:(次重點)
國家(country) 人口(population)
中國 600
美國 100
加拿大 100
英國 200
法國 300
日本 250
德國 200
墨西哥 50
印度 250
根據這個國家人口資料,統計亞洲和北美洲的人口數量。應該得到下面這個結果。
洲 人口
亞洲 1100
北美洲 250
其他 700
其中日本、中國、印度屬於亞洲,美國、加拿大、墨西哥屬於北美洲
SELECT CASE country WHEN '中國' THEN '亞洲' WHEN '日本' THEN '亞洲' WHEN '印度' THEN '亞洲'
WHEN '美國' THEN '北美洲' WHEN '加拿大' THEN '北美洲' WHEN '墨西哥' THEN '北美洲' ELSE '其它' END '國家'
,SUM(population)
FROM country
GROUP BY 1
練習:
一張學生成績表(tb_student)
FName FCores FScores
小明 語文 90
小明 數學 92
小明 英語 89
小紅 語文 91
小紅 數學 92
小紅 英語 80
要求,寫出合理的sql語句,得到下面的結果
姓名 語文 數學 英語
小明 90 92 89
小紅 91 92 80
1.7日期函式
1.7.1日期型別:
1.DATETIME:
型別用在你需要同時包含日期和時間資訊的值時。MySQL檢索並且以’YYYY-MM-DD HH:MM:SS’格式顯示DATETIME值,支援的範圍是’1000-01-01 00:00:00’到’9999-12-31 23:59:59’。(“支援”意味著儘管更早的值可能工作,但不能保證他們可以。)
2.DATE:
型別用在你僅需要日期值時,沒有時間部分。MySQL檢索並且以’YYYY-MM-DD’格式顯示DATE值,支援的範圍是’1000-01-01’到’9999-12-31’。
3.TIMESTAMP:
每張表的第一個timestamp會隨著插入與修改自動更新
可以表示年月日時分秒,你可以使用它自動地用當前的日期和時間標記INSERT或UPDATE的操作。
CREATE TABLE test(
i INT,
a TIMESTAMP,
b TIMESTAMP
)
INSERT INTO test(i) VALUES(1) #a欄位會自動更新為當前時間 b不會
SELECT * FROM test
4.TIME:
資料型別表示一天中的時間。MySQL檢索並且以"HH:MM:SS"格式顯示TIME值。支援的範圍是’00:00:00’到’23:59:59’。
1.7.2日期函式
1.系統當前時間函式
2.date_add函式
例如:查詢sing表,將所有入班日期加上一天
我們這兒使用的是date,無法操作時分秒
下面的類似上面的操作,這兒不演示了:
select date_add(now(), interval 1 day); -- 當前時間add 1 day
select date_add(now(), interval 1 hour); -- add 1 hour
select date_add(now(), interval 1 minute); -- ...
select date_add(now(), interval 1 second);
select date_add(now(), interval 1 microsecond);
select date_add(now(), interval 1 week);
select date_add(now(), interval 1 month);
select date_add(now(), interval 1 quarter);
select date_add(now(), interval 1 year);
select date_add(now(), interval -1 day); --減掉一天
#查詢來學習跳舞超過 800天
SELECT * FROM sing WHERE DATE_ADD(NOW(), INTERVAL -800 DAY)>s_begindate
3.timestampdiff函式
例如:
其他類似,不舉例了
#查詢來學習跳舞超過 800天
SELECT * FROM sing WHERE TIMESTAMPDIFF(DAY,s_begindate,NOW())>800
前面的日期 經過多少天到後面的日期
4.timestamp(瞭解)
練習3:
通過上面的函式,算出sing班級入班時間大於6000天的學生‘
答案見sql附件最後:
1.8null值處理
首先在mysql中,NULL表示的是“a missing unknown value”,而字串’'是一個確定的值,這本質上就已經不一樣了,NULL是指沒有值,而”則表示值是存在的,只不過是個空值
為了方便測試在sing表中新增一條記錄
1.null作為where條件是is null 或者 is not null 而不是=null
2.null值排序
用order by … asc時,null值會被放在最前面,而用order by … desc時,null時會被放在最後面,相當於null是一個無窮小的值。
3.count計算
Ifnull(xxx,0)
4.min、avg會忽略null值
5.ifnull函式
上面使用avg等的時候結果不是正確的,是因為null值的 原因,那麼我們在日常使用聚合函式的時候,可以使用ifnull函式
Ifnull(a,b) 表示如果a為null 就賦值為b
所以可以在計算中通過ifnull,根據你的邏輯來賦值計算,這兒用0
當然也可以在建立表的時候就指定預設值
6.null值加減乘除
為了方便測試,在sing表中加入一列
現在查詢s_level 與testnull 的和 (這個在實際中,也很多,比如工資加獎金)
大家以後在使用允許為null的欄位 進行計算時一定記住加上ifnull函式
1.9複製表
1.只複製表結構到新表
1 CREATE TABLE 新表 SELECT * FROM 舊錶 WHERE 1=2;
或
1 CREATE TABLE 新表 LIKE 舊錶 ;
注意上面兩種方式,前一種方式是不會複製時的主鍵型別和自增方式是不會複製過去的,而後一種方式是把舊錶的所有欄位型別都複製到新表。
比較簡單 其他自己練習一下
2.複製表結構及資料到新表
1 CREATE TABLE 新表 SELECT * FROM 舊錶
3.一張表資料插入到另一張表 (假設兩個表結構一樣)
INSERT INTO 新表 SELECT * FROM 舊錶
4.一張表資料插入到另一張表(假設兩個表結構不一樣)
1 INSERT INTO 新表(欄位1,欄位2,…) SELECT 欄位1,欄位2,… FROM 舊錶
# i與s_num 型別相同 a與s_begindate型別相同
INSERT INTO sing3(s_num,s_begindate) SELECT i,a FROM test
2.0常見考試sql題
1.用一條SQL 語句 查詢出每門課都大於80 分的學生姓名
Select * from score group by name having min(fenshu)>80
Select * from score where name not in(Select distinct name from score where fenshu<=80)
name kecheng fenshu
張三 語文 81
張三 數學 75
李四 語文 76
李四 數學 90
王五 語文 81
王五 數學 100
王五 英語 90
CREATE TABLE score(
NAME VARCHAR(2),
kecheng VARCHAR(2),
fenshu INT
)
INSERT INTO score VALUES('張三','語文',81),('張三','數學',75),('李四','語文',76),('李四','數學',90),
('王五','語文',81),('王五','數學',100),('王五','英語',90)
A:#先查出有分數低於80的同學 然後not in
SELECT DISTINCT NAME FROM score WHERE NAME NOT IN(
SELECT DISTINCT NAME FROM score WHERE fenshu<=80)
B:#找出每個同學的最低分 最低分大於80就可以了
select name from score group by name having min(ifnull(fenshu,0))>80
2.隨機在sing表中取三條資料
3.學生表student
自動編號 學號 姓名 課程編號 課程名稱 分數
1 2005001 張三 0001 數學 69
2 2005002 李四 0001 數學 89
3 2005001 張三 0001 數學 69
要求:表中除了自動編號相同,其他都不同的只保留一條
CREATE TABLE homework2(
id INT,
num INT,
NAME VARCHAR(2),
CODE VARCHAR(4),
kecheng VARCHAR(4),
fenshu INT
)
INSERT INTO homework2 VALUES(1,2005001,'張三','0001','數學',69),(3,2005001,'張三','0001','數學',69),
(2,2005002,'李四','0001','數學',89)
#上午學習了分組 要分組的每個欄位都相同才是一組 那麼就以除了id以外其它欄位分組
#其它欄位全是相同才是一組 取出最小或者最大的id 因為id不能重複 id只有一個,把其它id刪除了
#不允許查詢的時候刪除 複製一張表來刪除
CREATE TABLE homework SELECT * FROM homework2
DELETE FROM homework2 WHERE id NOT IN(
SELECT MIN(id) FROM homework GROUP BY num,NAME,CODE,kecheng,fenshu)
delete from xxx where 自動編號 not in(select min(自動編號) from xxx
Group by 學號,姓名,課程編號,課程分數,分數)
比如其中 張三的記錄重複輸入了,只保留一條
4.一個叫 team 的表,裡面只有一個欄位name, 一共有4 條紀錄,分別是a,b,c,d, 對應四個球對,現在四個球對進行比賽,用一條sql 語句顯示所有可能的比賽組合.注意ab與ba只能取一個
CREATE TABLE team(
NAME VARCHAR(1)
)
INSERT INTO team VALUES('a'),('b'),('c'),('d')
SELECT * FROM team
#規律就是每一隊都跟比它大的組合
SELECT CONCAT(t1.name,t2.name) FROM team t1 JOIN team t2 ON t1.name<t2.name