眾所周知,group by 子句是用來分組的,by后面跟上字段,表示以哪個字段之后,那么oracle和mysql的group by有何區別呢?接下來咱們就一起來探討一下。
共同點
寫法:select 字段1,字段2......
? ? ? ? ? ?from? 表
? ? ? ? ? ?where 條件
? ? ? ? ? group by? 字段
? ? ? ? ? having? ?條件;
注意:1.group by 必須配合聚合函數使用,聚合函數一般跟在select后
? ? ? ? ? ?2.如果分組后還要進行篩選,也就是說group by 后還要加條件的話,切記不能用where,要使用having
技巧:1.遇到統計想函數
????????????2.形容詞前group?by
????????????3.函數中央是名詞
????????????4.列名select后添加
? ? ? ?聲明:技巧來自老男孩oldguo大神
不同點
oracle:所有出現在select后面的字段名(函數用的字段不用管),必須出現在group by語句后,沒有在select后面出現的字段名,是不允許在group by后面的。
舉例:求同一部門 同一崗位有幾個人? (scott下的emp表)
select deptno ,job ,count(*)
from emp
group by deptno,job? ?;
?這里是按照2個字段的組合分成一組,另外各位看到deptno和job分別出現在select后面和group by 后面這樣才是正確的
select deptno ,job ,count(*)
from emp
group by deptno ;
如果group by 之后只跟deptno 就錯了
mysql:select后面出現的字段 ,除函數用的字段外,無需全部出現在group by 之后。
舉例:統計中國各個省的平均人口數,顯示結果是大于平均人口數的城市信息? (world庫里的city表)
SELECTcity.District,city.`Name`,city.`Population`,AVG(city.Population)
FROM city
WHERE city.countrycode='chn'
GROUP BY city.District
HAVING city.Population >??AVG(city.Population);
這條語句group by后面只跟了city.district一個字段,但是select后面除了函數所在字段外還有city.District,city.`Name`,city.`Population`,,共三個字段啊,如果是在oralce數據庫上,絕對會報錯,但是大家注意,我這里說的是mysql,而且是mysql5.6版本,所以,請大家不要懷疑,這條SQL絕對能執行成功,但是必須得是在mysql5.6上才能執行成功。也就是說如果你使用的是mysql5.7版本的話,就需要注意了,默認情況下,我說的是默認,這條語句是絕對執行不成功的。為什么呢?因為5.6和5.7版本不同(廢話,哈哈)
如果在5.7上要順利執行以上語句,有兩種辦法
第一種:加函數,把group by后面沒有但是select后面有的字段(函數所在字段除外)用any_value括起來。比如上述語句中,group by后面沒有但是select后面有的字段(函數所在字段除外)是city.`Name`,city.`Population`,那么就得把這兩個字段括起來,如:any_value(city.`Population`) ,any_value(city.name) ,正確的寫法如下:
SELECT city.`District`,any_value(city.`Population`) ap ,any_value(city.name) an , AVG(Population) avgp
FROM city
WHERE city.`CountryCode`='chn'
GROUP BY city.`District`
HAVING????ap > avgp;
為什么要加別名呢?這就是另外一個需要注意的地方了,使用having時,如果說需要原表數據和統計后的值進行比較時,需要在調用列的時候加全表名或者別名。怎么樣,記住了嗎?
第二種:修改sql_mode參數
SELECTcity.District,city.`Name`,city.`Population`,AVG(city.Population)
FROM city
WHERE city.countrycode='chn'
GROUP BY city.District
HAVING city.Population >??AVG(city.Population);
這條語句直接在5.7上使用的話絕對會報錯,罪惡的源頭就是sql_mode=only_full_group_by這個參數,只需把這個參數關掉即可。
ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUPBY clause and contains nonaggregated column 'world.city.Name' which is notfunctionally dependent on columns in GROUP BY clause; this is incompatible with?sql_mode=only_full_group_by
做法:
第一步:查看參數
select @@sql_mode;
+-------------------------------------------------------------------------------------------------------------------------------------------+
| @@sql_mode? ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ?? ? |
+-------------------------------------------------------------------------------------------------------------------------------------------+
|ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION|
+-------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
第二步:修改參數 注意:只是臨時修改,相當于會話變量,只在當前會話中生效。
setsql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
Query OK, 0 rows affected (0.00 sec)
第三步:執行SQL
mysql> SELECTcity.District,city.`Name`,city.`Population`,AVG(city.Population)
->
-> FROM city
->
-> WHERE city.countrycode='chn'
->
-> GROUP BY city.District
->
-> HAVING city.Population >?AVG(city.Population);
+----------------+---------------------+------------+----------------------+
| District? ? ? | Name? ? ? ?? ? ? ? | Population | AVG(city.Population) |
+----------------+---------------------+------------+----------------------+
| Anhui? ? ? ? ? | Hefei? ?? ? ? ? ? |? ? 1369100 |? ? ?? ? 321321.0000 |
| Fujian? ? ? ? | Fuzhou? ? ?? ? ? ? |? ? 1593800 |? ? ? ?? 297970.8333 |
| Gansu? ? ? ? ? | Lanzhou? ?? ? ? ? |? ? 1565800 |? ? ? ?? 351804.4286 |
| Guangdong? ? ? | Kanton [Guangzhou]?|? ? 4256300 |? ? ? ? ? 475513.1500 |
| Guangxi? ? ? ? | Nanning? ?? ? ? ? |? ? 1161800 |? ? ? ?? 325015.7778 |
| Guizhou? ? ? ? | Guiyang? ?? ? ? ? |? ? 1465200 |? ? ? ?? 418681.1667 |
| Hainan? ? ? ? | Haikou? ? ?? ? ? ? |? ? 454300 |? ? ? ?? 278560.0000 |
| Hebei? ? ? ? ? | Shijiazhuang?? ? ? |? ? 2041500 |? ? ? ? ?538212.7500 |
| Heilongjiang? | Harbin? ? ? ? ?? ? |? ? 4289800 |? ? ? ? ?553717.0000 |
| Henan? ? ? ? ? | Zhengzhou?? ? ? ? |? ? 2107200 |? ? ? ?? 383278.3333 |
| Hubei? ? ? ? ? | Wuhan? ?? ? ? ? ? |? ? 4344600 |? ? ?? ? 388526.5909 |
| Hunan? ? ? ? ? | Changsha?? ? ? ? ? |? ? 1809800 |? ? ?? ? 302181.9444 |
| Inner Mongolia | Baotou? ? ? ? ?? ? |? ? 980000 |? ? ? ? ? 317036.8462|
| Jiangsu? ? ? ? | Nanking [Nanjing]?|? ? 2870300 |? ? ? ? ? 388794.4000 |
| Jiangxi? ? ? ? | Nanchang? ?? ? ? ? |? ? 1691600 |? ? ? ?? 348323.4545 |
| Jilin? ? ? ? ? | Changchun?? ? ? ? |? ? 2812000 |? ? ? ?? 391341.2000 |
| Liaoning? ? ? | Shenyang? ? ?? ? ? |? ? 4265200 |? ? ? ? ?718055.9048 |
| Ningxia? ? ? ? | Yinchuan? ?? ? ? ? |? ? 544500 |? ? ? ?? 401181.0000 |
| Peking? ? ? ? | Peking? ? ?? ? ? ? |? ? 7472000 |? ? ? ?3784584.0000 |
| Shaanxi? ? ? ? | Xi′an? ? ?? ? ? ? |? ? 2761400 |? ? ? ?? 537186.6250 |
| Shandong? ? ? | Qingdao? ? ?? ? ? |? ? 2596000 |? ? ? ? ?378575.5000 |
| Shanxi? ? ? ? | Taiyuan? ?? ? ? ? |? ? 1968400 |? ? ? ?? 463322.1111 |
| Sichuan? ? ? ? | Chengdu? ?? ? ? ? |? ? 3361500 |? ? ? ?? 355088.9048 |
| Xinxiang? ? ? | Urumt?i [ürümqi]? ?|? ? 1310100 |? ? ? ? ? 289470.5000 |
| Yunnan? ? ? ? | Kunming? ?? ? ? ? |? ? 1829500 |? ? ? ?? 490203.2000 |
| Zhejiang? ? ? | Hangzhou? ? ?? ? ? |? ? 2190500 |? ? ? ? ?362961.5000 |
+----------------+---------------------+------------+----------------------+
26 rows in set (0.00 sec)
完美!!!
總結:1.oracle:所有出現在select后面的字段名(函數用的字段不用管),必須出現在group by語句后,沒有在select后面出現的字段名,是不允許在group by后面的。
2.使用having時,如果說需要原表數據和統計后的值進行比較時,需要在調用列的時候加全表名或者別名。
3.在select后的查詢里,必須是在group?by出現過的列,或者使用函數(any_value)將group by 后面沒有的列括起來的,否則會報錯。解決辦法一:加函數。二:改參數。
以上觀點僅代表一家之言,如有不足之處,歡迎大家批評指正。QQ:670340797? ?wechat:lhl9223