SQL查詢基礎
1、單表查詢
從數據庫中查找數據 專業的稱謂又稱為投影
基本查詢語句結構
select 列 from 表
* 所有列不是所有其他東西
查詢所有數據
例:SELECT * FROM t_studen
需要執行比較細的操作 加上條件篩選:查詢id為2號的學生信息
SELECT * FROM t_student WHERE id=2;
篩選的執行步驟
例:SELECT * FROM t_student WHERE id=2;
SELECT * (3) 再查詢 篩選完后 我最終投影的結果就是篩選后的結果,不是每行都顯示出來,顯示行的數據是篩選后的數據 所以最后執行 select
FROM t_student (1) 把整張表加到內存里面 把整張表找到后加到內存里面
WHERE id =2 (2) 篩選 因為一張表里面的數據需要去做一個篩選,不想讓每行都顯示,這樣就沒意義了,所以要進行一個條件篩選
只投影某些列
SELECT id,s_name FROM t_student; 只投影結果,而不是改變表數據,很多人會迷惑,其他列會不會不見了
查詢出來顯示成中文,比如s_name顯示成學生姓名
AS 加上別名 (列的別名)
SELECT id,s_name AS "學生姓名" FROM t_student;
表別名,當有幾張表的時候,表的名字很長,會給表加上別名
SELECT t_student.s_name FROM t_student -- 但是在一張表中這樣寫t_student.s_name 沒有任何意義
SELECT a.s_name FROM t_student a 本次查詢 a就代表t_student 就可以a.s_name
1.1、篩選掉重復數據 DISTINCT
SELECT DISTINCT s_name FROM t_student;
SELECT DISTINCT s_name,s_classid FROM t_student; distinct 要重復列(s_name,s_classid)的數據完全一樣
1.2、選擇操作:寫篩選條件的方法:
並且 and 也可以寫成&&
SELECT * FROM t_student WHERE id=2 AND s_name='李四' AND s_classid='二班'
SELECT * FROM t_student WHERE id=2 AND s_name='李四' && s_classid='二班'
或者 or 也可以寫成 ||
SELECT * FROM t_student WHERE s_classid='二班' OR id=1
SELECT * FROM t_student WHERE s_classid='二班' || id=1
范圍操作BETWEEN……AND……(包含)
語法:select 列 from 表名 where 列名 between 值 and 值;
SELECT * FROM t_student WHERE age>=18 AND age<=25
SELECT * FROM t_student WHERE age BETWEEN 18 AND 25 -- 等同於上面大於等於 及小於等於
小於等於18和一班,大於等於25和一班
SELECT * FROM t_student WHERE age<=18 OR age>=25 AND s_classid='一班';
這條語句執行出來的結果是小於等於18的所有數據和大於等於25並且是一班的數據
是因為and的優先級高於or的優先級
所以應該這樣寫:
SELECT * FROM t_student WHERE (age<=18 OR age>=25 ) AND s_classid='一班';
小於等於18和一班,大於等於25和一班 and優先級高於or 所以一般是單獨用括號括起來
查詢學生年紀為18 或者25 或者28
SELECT * FROM t_student WHERE age=18 OR age=25 OR age=28
in 操作
簡化上面的那種情況 where 列 in(值1,值2,值3)
SELECT * FROM t_student WHERE age IN(18,25,30)
not in 操作
值不是25的
SELECT * FROM t_student WHERE age NOT IN(25)
返回限定行數 limit
limit 數字=從第一行數據開始 數兩行
limit 數字n,數字m 從第n行數據開始(跟數組下標計算方式一樣) 數m行 跟字符串substr類似
SELECT * FROM t_student LIMIT 2
SELECT * FROM t_student LIMIT 2,2
返回第二行之后所有行 第二個參數足夠大 超出也只會返回到最后一行為止
SELECT * FROM t_student LIMIT 2,100
返回多少行 應用場景? 一些網站數據較多時,要出現分頁
1.3、模糊查詢
% 不限制字符
語法:select * from 表名 where 字段 like ‘x%’;
找所有姓張的學生
SELECT * FROM t_student WHERE s_name='張三' = 全匹配 不會幫你自動模糊查詢
SELECT * FROM t_student WHERE s_name LIKE '張%' like % 不限制字符(0-N個字符)的模糊查詢
SELECT * FROM t_student WHERE s_name LIKE '%張%' like % 可以查到包含張 如 *張*
SELECT * FROM t_student WHERE s_name LIKE '%張 like % 可以查到張,以張結尾, 但是不能是張**
占位符 _(下划線) 一個下划線代表一個字符
找所有姓張的學生,並且名字長度為三個字
SELECT * FROM t_student WHERE s_name LIKE '張__' like _ 限制字符數的模糊查詢 一個下划線代表一個字符
查詢年紀為空的學生信息
SELECT * FROM t_student WHERE age="" ''”代表為空白的值
空值 is null
SELECT * FROM t_student WHERE age IS NULL 代表空值 沒有輸入數據
不是空 is not null
SELECT * FROM t_student WHERE age IS NOT NULL
上面的操作 投影出來的東西 跟我們的表數據(輸入順序)中是一樣的順序,比如想讓它以
排序 order by 升序 ASC 降序 desc
年齡大小排序
SELECT * FROM t_student ORDER BY age -- 默認是升序
SELECT * FROM t_student ORDER BY age DESC -- 降序
SELECT * FROM t_student ORDER BY age ASC -- 升序
多於一個條件的排序
SELECT * FROM t_student ORDER BY age ASC,id ASC 會先讓age排序,
然后如果age有兩個一樣,再讓id排序age的順序,一般不會全部考慮,只有當兩條數據一樣,才考慮第二個條件
1.4、聚合函數
計數 count(列)
語法:select count(列) as ‘總數’ from 表名 where 條件 -------一般在計數的時候都會給取個別名
Count 統計時不包含沒有值的項
計算年齡在20歲的人數
例:SELECT COUNT(*) FROM t_student WHERE age=20
求和 sum(列)
語法:select sum(列) from 表名
例:SELECT SUM(age) FROM t_student
平均 avg
語法:(1)select sun(列)/count(*) from 表名
例:SELECT SUM(age)/COUNT(*) FROM t_student
(2)select avg(列) from 表名 -------默認不包含空
例:SELECT AVG(age) FROM t_student
(3)Select avg(ifnull(列,0)) from 表名 -----如果是空數據,補成0在求平均
例:SELECT AVG(IFNULL(age,0)) FROM t_student
最大值、最小值
語法:select max(列),min(列) from 表名
例:SELECT MAX(age),MIN(age) FROM t_student
分組 group by
語法:select 列名 ,count(*) from 表名 group by 需要分組的列名 (必須和前面的列相關聯)
select 列名 ,count(*) from 表名 group by 需要分組的列名 having 條件
例:查詢每一班的人數
SELECT s_classid,COUNT(*) FROM t_student GROUP BY s_classid;
顯示10歲(where)的人數大於2的班級的一條數據
SELECT s_classid,COUNT(*) FROM t_student WHERE age=10 GROUP BY s_classid HAVING(COUNT(*)>2);
執行步驟:
SELECT s_classid,COUNT(*) -- 4 投影
FROM t_student -- 1 把表加載到內存
WHERE age=10 -- 2 篩選
GROUP BY s_classid -- 3分組
HAVING(COUNT(*)>2) -- 5 二次篩選,首先要得到第一次的結果 才可以進行篩選
-- having跟where都是篩選條件,where是分組前,因為分組前沒有執行聚合函數
-- having是在分組后,只能用做聚合函數的過濾
顯示10歲(where)的人數大於1的班級並且按照人數排序
SELECT s_classid,COUNT(*) FROM t_student WHERE age=10 GROUP BY s_classid HAVING(COUNT(*)>=1) ORDER BY COUNT(*) limit 1
執行步驟:
SELECT s_classid,COUNT(*) -- 4 投影
FROM t_student -- 1 把表加載到內存
WHERE age=10 -- 2 篩選
GROUP BY s_classid -- 3 分組
HAVING(COUNT(*)>=1) -- 5 二次篩選 首先要得到第一次的結果 才可以進行篩選
ORDER BY COUNT(*) DESC -- 6 二次分組
LIMIT 1 -- 7 限定行數 肯定是你執行完之后最終的結果的 行數
-- 這7步順序千萬不能搞錯
2、多表查詢
2.1、相關子查詢
子查詢必須依賴於主查詢 ,子查詢單獨運行會報錯,依賴於主查詢的結果
select嵌套 只能返回單行單列
每次主查詢 執行一次,子查詢也會執行一次,最終執行N+1次,效率低下,如果主查詢沒有提供數據,子查詢無法執行
語法:select 列名1,列名2,(select 列名 from 表名 where 條件) from 表名
例:SELECT s_name,(SELECT c_name FROM t_class WHERE c_id=s_classid) FROM t_student
2.2 非相關子查詢
from 嵌套 必須要給嵌套的子查詢表起別名,可返回多行多列數據
子查詢對主查詢沒有依賴 子查詢只會執行一次,只會在from的時候才執行,性能較高,能獨立運行,只是給主查詢提供條件值
語法:select 列名1 ,列名2,.... from (select 列名 from 表名 [where 條件] ) [where 條件]
例:查詢性別為女 並且姓名為張三的
SELECT * FROM (SELECT * FROM t_student WHERE s_sex='女') AS t1
WHERE t1.s_name='張三';
where 嵌套 執行2次,子查詢可以單獨運行,不依賴主查詢,只是給主查詢提供條件值
語法:select 列名1,列名2, .... from 表名 where 列名 關系運算符 (select 列明 from 表名 where 條件)
例:查詢一班的學生有哪些
SELECT * FROM t_student WHERE s_classid=(SELECT c_id FROM t_class WHERE c_name='一班')
in 多條值
例:查詢一班的學生有哪些
語法:select 列名1,列名2,.... from 表名 where 列名 in (select 列明 from 表名 where 條件)
SELECT * FROM t_student WHERE s_classid in (SELECT c_id FROM t_class WHERE c_name='一班')
any 和all 必須跟子查詢 不能單獨使用
all 任意值
語法:select 列名1,列名2, .... from 表名 where 列名 關系運算符 all (select 列明 from 表名 where 條件)
例:查詢分數高於任意一個張三的所有學生 -- 使用all
SELECT * FROM t_student WHERE s_score>ALL(SELECT s_score FROM t_student WHERE s_name='張三')
any
語法:select 列名1,列名2, .... from 表名 where 列名 關系運算符 any (select 列明 from 表名 where 條件)
例:查詢分數高於任意一個張三的所有學生
SELECT * FROM t_student WHERE s_score>ANY( SELECT s_score FROM t_student WHERE s_name='張三');
還可以使用MIN
SELECT * FROM t_student WHERE s_score>(SELECT MIN(s_score) FROM t_student WHERE s_name='張三');
子查詢不管怎么變,都只有三種,在where中嵌套一個,form 一個,select一個