MySQL运维实战系列:MySQL5.7 Group By 问题
一、環(huán)境
MySQL版本:MySQL5.7.22表結(jié)構(gòu):CREATE TABLE `crm_report_accounting_income` (`id` int(10) NOT NULL AUTO_INCREMENT,`contract_id` int(10) NOT NULL,`contract_no` varchar(50) NOT NULL,`date` int(8) NOT NULL,`city_id` int(11) NOT NULL DEFAULT '0' COMMENT '城市id',`city_name` varchar(50) DEFAULT NULL,`adviser_id` int(10) NOT NULL,`adviser_name` varchar(50) DEFAULT NULL,`accounting` decimal(15,2) NOT NULL COMMENT 'xx',`receivable` decimal(15,2) NOT NULL DEFAULT '0.00' COMMENT '當(dāng)xx',`contract_type` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1:xx合同;2:xx合同;3:xx合同',PRIMARY KEY (`id`),KEY `contract_id` (`contract_id`),KEY `date` (`date`),KEY `city_id` (`city_id`) ) ENGINE=InnoDB AUTO_INCREMENT=734525 DEFAULT CHARSET=utf8二、業(yè)務(wù)問(wèn)題
* 基本信息,由于合同號(hào)太多,所以這邊就以一個(gè)有重復(fù)數(shù)據(jù)的合同id為例dba:aif_db> select contract_id,contract_no,receivable,date from crm_report_accounting_income_2015_online where contract_id = 27310; +-------------+----------------------------+------------+----------+ | contract_id | contract_no | receivable | date | +-------------+----------------------------+------------+----------+ | 27310 | A00-SHEN-05-2018-06-004613 | 2941.18 | 20180628 | | 27310 | A00-SHEN-05-2018-06-004613 | 5882.36 | 20180629 | | 27310 | A00-SHEN-05-2018-06-004613 | 8823.54 | 20180630 | | 27310 | A00-SHEN-05-2018-06-004613 | 11764.72 | 20180701 | | 27310 | A00-SHEN-05-2018-06-004613 | 14705.90 | 20180702 | | 27310 | A00-SHEN-05-2018-06-004613 | 17647.08 | 20180703 | | 27310 | A00-SHEN-05-2018-06-004613 | 20588.26 | 20180704 | | 27310 | A00-SHEN-05-2018-06-004613 | 23529.44 | 20180705 | | 27310 | A00-SHEN-05-2018-06-004613 | 26470.62 | 20180706 | | 27310 | A00-SHEN-05-2018-06-004613 | 29411.80 | 20180707 | | 27310 | A00-SHEN-05-2018-06-004613 | 32352.98 | 20180708 | | 27310 | A00-SHEN-05-2018-06-004613 | 35294.16 | 20180709 | +-------------+----------------------------+------------+----------+ 12 rows in set (0.00 sec)* 查詢每個(gè)最新合同的信息,由于合同號(hào)太多,所以這邊就以一個(gè)有重復(fù)數(shù)據(jù)的合同id為例select contract_no, contract_id, city_name, receivable,date from (select * from crm_report_accounting_income_2015_online where contract_id = 27310 ORDER BY `date` desc) p GROUP BY contract_id+----------------------------+-------------+-----------+------------+----------+ | contract_no | contract_id | city_name | receivable | date | +----------------------------+-------------+-----------+------------+----------+ | A00-xxxx-05-2018-06-xxxxxx | xxxxx | 沈陽(yáng) | 2941.18 | 20180628 | +----------------------------+-------------+-----------+------------+----------+ 1 row in set (0.00 sec)以上看到的寫法,是通過(guò)子查詢寫的,5.6查詢沒(méi)問(wèn)題,5.7就變成了以上的結(jié)果,很明顯得到的答案不是業(yè)務(wù)想要的
究其原因還是因?yàn)?#xff0c;MySQL5.7 sql mode更加嚴(yán)格了,如果設(shè)置sql_mode = ONLY_FULL_GROUP_BY, 那么以上SQL就會(huì)報(bào)錯(cuò)
因?yàn)閟ql_mode = ONLY_FULL_GROUP_BY 要求符合SQL 92標(biāo)準(zhǔn),即:select列表里只能出現(xiàn)分組列(即group by后面的列)和聚合函數(shù)(max,min等等)
然而為了兼容5.6,我們?cè)O(shè)置sql_mode='', 所以我們的Group by 在子查詢中就跟5.6就不一致了
當(dāng)然,我們應(yīng)該避免不標(biāo)準(zhǔn)的SQL寫法,這樣的問(wèn)題,我們的解法就是調(diào)整業(yè)務(wù)的SQL語(yǔ)句,改寫成SQL 92標(biāo)準(zhǔn)的語(yǔ)法
那么以上SQL語(yǔ)句應(yīng)該調(diào)整為:
selectcontract_no,e.contract_id,city_name,receivable,date fromcrm_report_accounting_income_2015_online e,( select contract_id , max(date) max_date from crm_report_accounting_income_2015_online where contract_id = 27310 group by contract_id ) t wheree.contract_id = t.contract_idand e.date = t.max_date+----------------------------+-------------+-----------+------------+----------+ | contract_no | contract_id | city_name | receivable | date | +----------------------------+-------------+-----------+------------+----------+ | A00-xxxx-05-2018-06-004613 | 27310 | xxxx | 35294.16 | 20180709 | +----------------------------+-------------+-----------+------------+----------+ 1 row in set (0.00 sec)以上都還是需要業(yè)務(wù)代碼修改,這樣如果沒(méi)有提前發(fā)現(xiàn)問(wèn)題,豈不是會(huì)導(dǎo)致業(yè)務(wù)出錯(cuò)了?有沒(méi)有更好的辦法?
MySQL方面其實(shí)還是可以配置相關(guān)的參數(shù)的:
dba:aif_db> set optimizer_switch='derived_merge=off'; Query OK, 0 rows affected (0.00 sec)dbadmin:aifangcrm_db> select contract_no, contract_id, city_name, receivable,date from-> (select * from crm_report_accounting_income_2015_online where contract_id = 27310 ORDER BY `date` desc) p GROUP BY contract_id-> ; +----------------------------+-------------+-----------+------------+----------+ | contract_no | contract_id | city_name | receivable | date | +----------------------------+-------------+-----------+------------+----------+ | A00-xxxx-05-2018-06-004613 | 27310 | xxxx | 35294.16 | 20180709 | +----------------------------+-------------+-----------+------------+----------+ 1 row in set (0.00 sec)三、總結(jié)
- SQL語(yǔ)法應(yīng)該要按照標(biāo)準(zhǔn)的SQL92來(lái)寫
- 數(shù)據(jù)庫(kù)升級(jí)到5.7之后,應(yīng)該提前監(jiān)控處group by + 子查詢的情況,提前告知業(yè)務(wù)修改業(yè)務(wù)代碼
- 設(shè)置參數(shù)也能解決問(wèn)題,但是這個(gè)參數(shù)畢竟是5.7新增的,如果關(guān)閉后,以后會(huì)不會(huì)導(dǎo)致其他的bug就不知曉了
最后,還是希望能夠修改query 語(yǔ)句到標(biāo)準(zhǔn)語(yǔ)法,如果出現(xiàn)業(yè)務(wù)問(wèn)題,可以讓業(yè)務(wù)修改參數(shù)快速解決問(wèn)題,然后再修改語(yǔ)句比較與時(shí)俱進(jìn)
總結(jié)
以上是生活随笔為你收集整理的MySQL运维实战系列:MySQL5.7 Group By 问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: hdu-3790最短路径问题
- 下一篇: HDU 5624 KK's Recons