Group by函數
1.前言
在數據庫操作中分組操作經常用到。本文就來聊一聊,數據庫中分組函數GROUP BY ;
2.創建測試表
示例表
CREATE TABLE `group_by_test` (
`id` INT ( 10 ) NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`field_one` VARCHAR ( 64 ) NOT NULL DEFAULT '' COMMENT '字段1',
`field_two` VARCHAR ( 64 ) NOT NULL DEFAULT '' COMMENT '字段2',
`field_three` VARCHAR ( 64 ) NOT NULL DEFAULT '' COMMENT '字段3',
PRIMARY KEY ( `id` ) USING BTREE
) ENGINE = INNODB DEFAULT CHARSET = utf8 COMMENT = 'group by 函數測試表';
3.SELECT後允許跟非分組字段嗎?
問題:這個SQL可以執行嗎?
SELECT
field_one,
field_two,
field_three
FROM
group_by_test
GROUP BY field_one
答案:執行以上SQL是需要有條件的 ;
mysql數據庫的中有一個環境變量sql_mode,定義了mysql應該支持的sql語法,數據校驗等!
如果ONLY_FULL_GROUP_BY啓用了 SQL模式(默認情況下爲SQL模式),則MySQL拒絕查詢
MySQL官網中是這樣介紹的:
簡譯:
- 不允許選擇列表,HAVING條件或ORDER BY列表引用未在GROUP BY子句中命名的未聚合列的查詢;
綜上所述:
如果在SELECT中的列,沒有在GROUP BY中出現,若ONLY_FULL_GROUP_BY
啓用了 SQL模式那麼將認爲這個SQL是不合法的,
查看
查看當前連接會話的sql模式:
mysql> select @@session.sql_mode;
或者從環境變量裏取
mysql> show variables like "sql_mode";
查看全局sql_mode設置:
mysql> select @@global.sql_mode;
只設置global,需要重新連接進來纔會生效
sql_mode值與含義
ONLY_FULL_GROUP_BY | 對於GROUP BY聚合操作,如果在SELECT中的列,沒有在GROUP BY中出現,那麼將認爲這個SQL是不合法的,因爲列不在GROUP BY從句中 |
---|---|
STRICT_TRANS_TABLES | 在該模式下,如果一個值不能插入到一個事務表中,則中斷當前的操作,對非事務表不做任何限制 |
NO_ZERO_IN_DATE | 在嚴格模式,不接受月或日部分爲0的日期。如果使用IGNORE選項,我們爲類似的日期插入’0000-00-00’。在非嚴格模式,可以接受該日期,但會生成警告。 |
NO_ZERO_DATE | 在嚴格模式,不要將 '0000-00-00’做爲合法日期。你仍然可以用IGNORE選項插入零日期。在非嚴格模式,可以接受該日期,但會生成警告 |
ERROR_FOR_DIVISION_BY_ZERO | 在嚴格模式,在INSERT或UPDATE過程中,如果被零除(或MOD(X,0)),則產生錯誤(否則爲警告)。如果未給出該模式,被零除時MySQL返回NULL。如果用到INSERT IGNORE或UPDATE IGNORE中,MySQL生成被零除警告,但操作結果爲NULL。 |
NO_AUTO_CREATE_USER | 防止GRANT自動創建新用戶,除非還指定了密碼。 |
NO_ENGINE_SUBSTITUTION | 如果需要的存儲引擎被禁用或未編譯,那麼拋出錯誤。不設置此值時,用默認的存儲引擎替代,並拋出一個異常。 |
設置
形式如
mysql> set sql_mode='';
mysql> set global.sql_mode='NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES';
或者替換ONLY_FULL_GROUP_BY爲''
set @@session.sql_mode=(select replace(@@session.sql_mode,'ONLY_FULL_GROUP_BY',''));
不啓用ONLY_FULL_GROUP_BY
SQL模式使用Group_by 數據是怎麼獲取的?
官方是這樣解釋的
簡翻重點:服務器可以從每個組中自由選擇任何值 ;
自己試驗一下
模擬數據
INSERT INTO `group_by_test`
(`id`, `field_one`, `field_two`, `field_three`)
VALUES
(1, '1', '', '3-1'),
(2, '1', '2-2', '3-2'),
(3, '1', '2-3', '3-3'),
(4, '1', '', '3-4'),
(5, '1', '2-5', '');
模擬結果:非GROUP BY 子句列,默認取的第一行數據填充