注:該MySql系列博客僅為個人學習筆記。
這篇博客主要記錄sql的五種子句查詢語法!
一個重要的概念:將字段當做變量看,無論是條件,還是函數,或者查出來的字段。
select五種子句
where 條件查詢
group by 分組
having 篩選
order by 排序
limit 限制結果條數
為了練習上面5種子句,先建立一張goods表,主要用於查詢操作,表結構如下:
所有數據:

1.基礎查詢 —— where
where常用運算符:

1.1 查出主鍵為20的商品
:mysql> SELECT goods_id,cat_id,goods_sn,goods_name,goods_number,is_hot FROM goods WHERE goods_id = 20;

1.2 查出不屬於第三類的所有商品
:mysql> SELECT goods_id,cat_id,goods_sn,goods_name,click_count,is_best FROM goods WHERE cat_id != 3;

:mysql> SELECT goods_id,cat_id,goods_sn,goods_name,click_count,is_best FROM goods WHERE cat_id <> 3;

1.3 查詢高於3000元的商品
:mysql> SELECT goods_id,cat_id,goods_name,shop_price,is_new FROM goods WHERE shop_price > 3000;

1.4 查詢低於或等於100元的商品
:mysql> SELECT goods_id,goods_name,goods_number,shop_price FROM goods WHERE shop_price <= 100;

1.5 取出第4類和第11類的商品
:mysql> SELECT cat_id,goods_name,shop_price FROM goods WHERE cat_id IN (4,11);

1.6 取出不在第3類和第11類的商品
:mysql> SELECT goods_id,cat_id,goods_name FROM goods WHERE cat_id != 3 && cat_id != 11;

not in 方式實現
:mysql> SELECT goods_id,cat_id,goods_name FROM goods WHERE cat_id NOT IN (3,11);

1.7 取出 100 <= 價格 <= 500 的商品
:mysql> SELECT goods_id,cat_id,goods_name,shop_price FROM goods WHERE shop_price >= 100 && shop_price <= 500;

使用between,可以看出是包括邊界值的
:mysql> SELECT goods_id,cat_id,goods_name,shop_price FROM goods WHERE shop_price between 100 AND 500;

1.8 取出價格大於100且小於300,或者大於3000且小於5000的商品
:mysql> SELECT goods_id,cat_id,goods_name,shop_price
-> FROM goods
-> WHERE shop_price > 100 AND shop_price < 300
-> OR shop_price > 3000 AND shop_price < 5000;

取出價格大於100且小於300,或者大於4000且小於5000的商品
:mysql> SELECT goods_id,goods_name,shop_price FROM goods WHERE shop_price between 100 AND 300 OR shop_price between 4000 AND 5000;

like模糊查詢
1.9 查出以"諾基亞"開頭的商品; "%"通配任意字符
:mysql> SELECT goods_id,goods_name,goods_sn,shop_price FROM goods WHERE goods_name LIKE "諾基亞%";

1.10 取出以"諾基亞N"開頭,且后面有兩個字符的商品; "_"通配單一字符
:mysql> SELECT goods_id,goods_name,shop_price FROM goods WHERE goods_name LIKE "諾基亞N__";

1.11 取出第三個欄目下面價格在1000到3000之間,並且點擊量 > 5 "諾基亞"開頭的系列商品
:mysql> SELECT goods_id,goods_name,click_count,shop_price FROM goods WHERE shop_price BETWEEN 1000 AND 3000 AND click_count > 5 AND goods_name LIKE "諾基亞%";

1.12 取出本店價格比市場價格省的錢
:mysql> SELECT goods_name AS '商品名', shop_price AS '本店價格', market_price AS '市場價格', market_price - shop_price AS '省錢' FROM goods WHERE goods_name LIKE "諾基亞%"

1.13 取出省錢200以上的商品;注意where后還是用的運算表達式。
:mysql> SELECT goods_name AS name, shop_price AS shopPrice, market_price AS marketPrice, (market_price-shop_price) AS discount FROM goods WHERE (market_price-shop_price) >= 200;

## where后面不能直接用別名進行表達式判斷,會報錯,因為where查詢是根據表中字段進行查詢;查詢出來的是一個結果集(可以包含表中沒有的字段),如果想對結果集再篩選,可以用having篩選!
:mysql> SELECT goods_name AS '商品名', shop_price AS '本店價格', market_price AS '市場價格', market_price - shop_price AS '省錢' FROM goods WHERE discount >= 200; 錯誤!

#having再次篩選
:mysql> SELECT goods_name AS name, shop_price AS shopPrice, market_price AS marketPrice, (market_price - shop_price) AS discount FROM goods having discount >= 200;

2. group by 與 統計函數
max:求最大
min:求最小
sum:求和
avg:求平均
count: 求總行數
2.1 查出最貴的商品
:mysql> SELECT max(shop_price) FROM goods;

2.2. 查出最便宜的商品價格
:mysql> SELECT min(shop_price) FROM goods;

2.3 查詢總庫存量
:mysql> SELECT sum(goods_number) FROM goods;

2.4 查看所有商品的平均價格
:mysql> SELECT avg(shop_price) FROM goods;

2.5 統計共有多少個商品
:mysql> SELECT count(1) FROM goods;

:mysql> select count(name) from test1;
如果count()的字段為NULL是不會計數的

:mysql> select count(*) from test1;

select count(*) 查詢的是絕對的行數,就算某行全為NULL,也計算在內。
select count(列名) 查詢的是該列不為NULL的所有行的行數。
count(*)和count(1)的區別:對於MyIsam引擎的表,是沒有區別的,這種引擎內部有一計數器在維護着行數;如果是InnoDB的表,用count(*) 直接讀行數,效率很低,因為會一行行數!
2.6 查詢第三類下商品總數
:mysql> select sum(goods_number) from goods where cat_id = 3;

2.7 查詢每個類別下的商品總量
:mysql> SELECT cat_id, sum(goods_number) FROM goods GROUP BY cat_id;
group by 有多少個類別,就有多少行

:mysql> SELECT sum(goods_number) FROM goods GROUP BY cat_id;

對於SQL標准來說,下面兩個語句是錯誤的,不能執行。但是在MySql中可以這么干。只是默認查出第一個值而已,但是並沒能一一對應。出於可移植性和規范性,不推薦這樣寫!
嚴格來說,使用group by a,b,c 時,則select查詢的列,只能在a,b,c里選擇,語義上才沒有矛盾,才能一一對應起來!!!
:mysql> SELECT goods_id, sum(goods_number) FROM goods;(非SQL標准)

:mysql> SELECT goods_name, sum(goods_number), cat_id FROM goods GROUP BY cat_id; (非SQL標准)

2.8 查詢每個類別下商品的平均價格
:mysql> SELECT cat_id, avg(shop_price) FROM goods GROUP BY cat_id;

3. having
3.1 查詢每個商品所積壓的貨款
:mysql> SELECT goods_id,goods_name,goods_number,shop_price, (goods_number * shop_price) AS 'total_price' FROM goods;

3.2 查詢積壓的總貨款
:mysql> SELECT SUM(goods_number * shop_price) AS '總貨款' FROM goods;

3.3 查詢每個類別下積壓的貨款
:mysql> SELECT cat_id, SUM(goods_number * shop_price) AS 'total_money' FROM goods GROUP BY cat_id;

3.4 查詢某個類別下積壓的貨款大於20000的
:mysql> SELECT cat_id, SUM(goods_number * shop_price) AS 'total_money' FROM goods GROUP BY cat_id HAVING total_money >= 20000;

3.5 查詢比市場價省200以上的商品,以及該商品所省的錢
:mysql> SELECT goods_name,market_price,shop_price, (market_price - shop_price) AS 'price' FROM goods WHERE (market_price - shop_price) >= 200;
where方式造成計算浪費,所以可以使用having進行結果集篩選。

:mysql> SELECT goods_name,market_price,shop_price, (market_price - shop_price) AS 'price' FROM goods HAVING price >= 200;

4.where + group by + having + 函數 綜合查詢
練習表:

4.1 查詢出兩門及兩門以上不及格者的平均成績(注意是所有科目的平均成績)
:mysql> SELECT name, avg(score) FROM stu WHERE score < 60 GROUP BY name having count(1) >= 2; 錯誤!

:mysql> SELECT name,avg(score),count(score<60) AS 'count' FROM stu GROUP BY name HAVING count >= 2;錯誤!
count(a),無論a是什么,都只是數一行;count時,每遇到一行,就數一個a,跟條件無關!

:mysql> SELECT name,avg(score), sum(score<60) as 'gk' FROM stu GROUP BY name having gk >= 2;
解析:count(score<60)達不到想要的結果,並不是條件的問題,而是無論count()里的表達式是什么都會數一行。
score<60 返回 1 或 0;所以可以用sum(score<60)來計算不及格的科目數!

sum()和count()在某種程度上可以互換。

5. order by + limit
5.1 取出第四類的商品,並按價格由高到低
:mysql> SELECT goods_name,cat_id,shop_price FROM goods WHERE cat_id = 4 ORDER BY shop_price DESC;
order by(排序) 是針對最終結果集,所以order by 要放在where/group by/having 后面。降序:desc; 升序:asc.

5.2 按類別升序排列,同一類別下的商品按價格降序排列
:mysql> SELECT goods_name,cat_id,shop_price FROM goods GROUP BY cat_id ORDER BY cat_id ASC,shop_price DESC;
若有多個列需要排序,首先按第一個排序,再按后面的列排序

5.3 按類別降序排列,同一類別下的商品按價格升序排列(使用別名)
:mysql> SELECT goods_name AS 'name', cat_id AS 'catId', shop_price AS 'price' FROM goods GROUP BY catId ORDER BY catId DESC, shop_price ASC;
order by 查詢是針對結果集查詢的。

5.4 查詢前10數據
:mysql> SELECT goods_id,goods_name,cat_id,shop_price FROM goods LIMIT 10;
limit放在最后,用於限制查出的記錄數。

5.5 查詢價格最高的前三件商品
:mysql> SELECT goods_name,cat_id,goods_number,shop_price FROM goods ORDER BY shop_price DESC LIMIT 3;

5.6 取出價格最高的前3至5件商品
:mysql> SELECT goods_name,cat_id,goods_number,shop_price FROM goods ORDER BY shop_price DESC LIMIT 2,3;

------------------------------------------------------------------------------------------------------------------------------------------------------------------------
五種子句總結:
1.select a,b,c from table where x = 1; ==》》 where條件的 變量x 必須在表中存在;where是針對表做操作。
2.select a, b, c AS x having x = 1; ==》》 having 后的變量 x 可以是表中的列,也可以是別名,having是對查詢結果集進行再篩選。這點區別於where,如果where使用別名,則會報"unknown column"錯誤;having是針對結果集做操作。
3.select count(*) 查詢的是絕對的行數,就算某行全為NULL,也計算在內。
select count(列名) 查詢的是該列不為NULL的所有行的行數。
count(*)和count(1)的區別:對於MyIsam引擎的表,是沒有區別的,這種引擎內部有一計數器在維護着行數;如果是InnoDB的表,用count(*) 直接讀行數,效率很低,因為會一行行數!
count(a<60),a<60返回值要么為1,要么為0,所以count()都會數一行,達不到根據條件數行數的目的;換一種思維,如果想計算a<60的行數,可以用sum(a < 60),滿足a<60的返回 1,不滿足返回 0。
sum()在某種程度上可以替換count()!
4.group by 有多少個類別,查出來就有多少行數據。
group by是針對where查詢的結果集做操作!
使用group by a,b,c 時,則select查詢的列,只能在a,b,c里選擇,語義上才沒有矛盾,才能一一對應起來。
group by a desc:這是一種錯誤的寫法,group by 是沒有排序功能的。
5.order by 是針對最終結果集進行排序的!所以放在where/group by/having 后面。降序:DESC; 升序:ASC。
若有多個列需要排序,首先按第一個排序,再按后面的列排序;多個列排序用","隔開。
6.limit [offset,] N :offset 偏移量,如果不寫則為0(從0開始);N取出條目;
7.where是針對表做操作;having / group by / order by / limit 是針對結果集做操作,且先后順序固定;where查詢列只能是表字段,其余的查詢列既可以是表字段,也可以是別名。
