目录场景:查询各部门薪水最高的员工。MySQLgroupby是如何决定哪一条数据留下的?那么targetlist和groupbycolumn不匹配就一定不能执行吗? MySQL版本:8。0。27场景:查询各部门薪水最高的员工。CREATETABLEemployee(idintNOTNULLAUTOINCREMENTCOMMENT主键ID,deptintNOTNULLCOMMENT部门,uservarchar(32)CHARACTERSETutf8COLLATEutf8generalciNOTNULLCOMMENT员工,salaryintNULLDEFAULTNULLCOMMENT薪水,isdeletedtinyint(1)NOTNULLDEFAULT0COMMENT是否删除,remarkvarchar(512)CHARACTERSETutf8COLLATEutf8generalciNULLDEFAULTNULLCOMMENT备注,modifytimedatetime(3)NOTNULLDEFAULTCURRENTTIMESTAMP(3)ONUPDATECURRENTTIMESTAMP(3)COMMENT修改时间,PRIMARYKEY(id)USINGBTREE)ENGINEInnoDBCHARACTERSETutf8COLLATEutf8generalciCOMMENT员工ROWFORMATDINSERTINTOemployeeVALUES(1,1,张三,1000,0,NULL,2021122309:20:19。606);INSERTINTOemployeeVALUES(2,1,李四,1500,0,NULL,2021122309:20:21。679);INSERTINTOemployeeVALUES(3,1,王五,2000,0,NULL,2021122309:20:23。371);INSERTINTOemployeeVALUES(4,2,赵六,1000,0,NULL,2021122309:21:59。373);INSERTINTOemployeeVALUES(5,2,孙七,1500,0,NULL,2021122309:22:15。000); SELECTFROM 方法一:SELECTt1。FROMemployeet1LEFTJOINemployeet2ONt2。deptt1。deptANDt1。salaryt2。salaryWHEREt2。salaryISNULL; 方法二:SELECTFROM(SELECTFROMemployeeORDERBYdept,salaryDESCLIMIT1000)tGROUPBY (不加limit可能会失效) 看起来结果是一样的,但第二种其实是会有问题的。MySQLgroupby是如何决定哪一条数据留下的? MySQL通过sqlmode来提供SQL语句的合法性检查, 在默认情况下,MySQL允许查询列targetlist中出现除了groupbycolumn、聚集函数等以外的表达式。 但是,那些不参与groupby的字段具体会返回哪条数据的值在MySQL中是处于未定义规则的状态, MySQL不承诺一定会返回哪条数据。分组前的数据: SELECTFROMemployeeORDERBYdept,salaryDESCLIMIT1000; 看起来方法二返回的是每个分组中的第一条的数据, 但实际上还会与存储引擎、物理位置、索引等有关, 如果是InnoDB的话,取决于在BTree上命中的第一条索引, 这里不展开说明,毕竟不是安全的用法, 有的时候可能返回的结果并不是我们想要的。 关于BTree,可以看下这篇文章: 通过BTree平衡多叉树理解InnoDB引擎的聚集和非聚集索引 所以对于targetlist中出现的不明确的列,MySQL是不确定哪一条数据留下的。 对于语法限制比较严格的数据库,都不支持targetlist中出现语义不明确的列, MySQL中提供了一个修正的sqlmode,ONLYFULLGROUPBY。SETSESSIONsqlmodeONLYFULLGROUPBY; 再执行方法二的SQL就被拒绝了:SELECTFROM(SELECTFROMemployeeORDERBYdept,salaryDESCLIMIT1000)tGROUPBYdept1055Expression1ofSELECTlistisnotinGROUPBYclauseandcontainsnonaggregatedcolumnt。idwhichisnotfunctionallydependentoncolumnsinGROUPBYthisisincompatiblewithsqlmodeonlyfullgroupby时间:0s onlyfullgroupby模式下MySQL会对targetlist和groupbycolumn中的基础列、表达式、别名列进行严格匹配。那么targetlist和groupbycolumn不匹配就一定不能执行吗? 我们看下另外一条SQL:订单CREATETABLEorder(orderidintNOTNULLAUTOINCREMENTCOMMENT订单ID,orderamountintNULLDEFAULTNULLCOMMENT订单金额,PRIMARYKEY(orderid)USINGBTREE)ENGINEInnoDBCHARACTERSETutf8COLLATEutf8generalciCOMMENT订单ROWFORMATDYNAMIC;INSERTINTOorderVALUES(1,100);INSERTINTOorderVALUES(2,103);INSERTINTOorderVALUES(3,100);订单明细CREATETABLEorderdetail(orderdetailidintNOTNULLAUTOINCREMENTCOMMENT主键ID,orderidintNOTNULLCOMMENT订单ID,goodsvarchar(32)CHARACTERSETutf8COLLATEutf8generalciNOTNULLCOMMENT商品名称,goodsamountintNOTNULLCOMMENT商品金额,PRIMARYKEY(orderdetailid)USINGBTREE)ENGINEInnoDBCHARACTERSETutf8COLLATEutf8generalciCOMMENT订单明细ROWFORMATDYNAMIC;INSERTINTOorderdetailVALUES(1,1,苹果,10);INSERTINTOorderdetailVALUES(2,1,橙子,20);INSERTINTOorderdetailVALUES(3,1,香蕉,70);INSERTINTOorderdetailVALUES(4,2,橘子,50);INSERTINTOorderdetailVALUES(5,2,菠萝,53); 查询订单中所有商品SELECTt1。orderid,t1。orderamount,GROUPCONCAT(t2。goods,t2。goodsamount)FROMordert1LEFTJOINorderdetailt2ONt2。orderidt1。orderidGROUPBYt1。 这条SQL的targetlist和groupbycolumn并不是严格匹配的,但是也可以执行, 注意 t1。orderid是订单表的主键。 所以在onlyfullgroupby模式下,如果MySQL可以确定targetlist中所有列的返回值, 那么,即使targetlist和groupbycolumn中的基础列、表达式、别名列等不严格匹配, MySQL也会认为它的语义是明确的,因此该条语句可以顺利通过。 原文http:www。cnblogs。comcaptaincatp15723369。html