Msql与sql_mode = only_full_group_by不兼容

时间:2016-08-09 07:07:14

标签: mysql mysql-error-1064

我在linux中使用mysql版本5.7.13

当我运行存储过程时,我收到以下错误

ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause 
and contains nonaggregated column 'medigurus.pp.physicianid' which is not
   functionally dependent on columns in GROUP BY clause; this is  
 incompatible with sql_mode=only_full_group_by

我的程序是

 DELIMITER $$ DROP PROCEDURE IF EXISTS medigurus.getPatientDoctors$$ CREATE 
 DEFINER=root@localhost PROCEDURE getPatientDoctors(IN patientid INT(10)) 
 BEGIN SELECT pp.physicianid, d.physiciantypeid, p.firstname, p.lastname, 
 p.dob, p.mobile, p.officephone, p.address1, p.address2, p.city, p.stateid, 
 p.cid, p.zip,p.speciality, p.about, p.imgid FROM patientphysicians pp INNER 
 JOIN physician p ON pp.physicianid = p.physicianid INNER JOIN 
  getpatientdoctorsview AS d ON d.patientid=pp.patientid WHERE pp.patientid 
      = patientid GROUP BY p.physicianid; END$$ DELIMITER ; 

并且查看

    DELIMITER $$

DROP VIEW IF EXISTS `medigurus`.`getpatientdoctorsview`$$

 CREATE ALGORITHM=UNDEFINED 
DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `getpatientdoctorsview`    AS
  select `pp`.`physicianid` AS `physicianid`,`pp`.`patientid` AS 
`patientid`,group_concat(`pp`.`physiciantypeid` separator ',') AS  
 `physiciantypeid`
   from `patientphysicians` `pp` group by `pp`.`patientid`$$

   DELIMITER ;

如何解决错误..

1 个答案:

答案 0 :(得分:1)

快速解决方案是将聚合函数应用于medigurus.pp.physicianid,如下所示:

select ...  min(medigurus.pp.physicianid) as physicianid, ...

错误消息的原因是medigurus.pp.physicianid不明确,因为每个组可能有多个值,而SQL引擎需要选择一个。没有这个设置(限制),它只会占用它遇到的第一个,但是这种行为不符合SQL标准。

但是,通过指明要返回的这些值中的哪一个(例如,通过min),您可以解决问题。

禁用“仅限完整分组”选项

或者,尽管没有建议,但您可以通过清除此选项返回到MySql的旧行为:

SET sql_mode = ''

关于程序和观点

正如您在更新问题时提供的实际SQL,我在此添加了我的观察结果:

视图的select patientid 对结果进行分组,以便汇总相关医生的类型。但是,您也选择 physicianid :这没有什么意义,因为一般情况下您可能有几个不同的医生与一个患者相关联,因此其价值不是单数。您应该省略该字段 - 或者如果您确实需要每位患者一位医生,您应该问自己一个问题:哪一个,如果有多个?在这里,我建议省略它:

select   patientid AS patientid,
         group_concat(physiciantypeid separator ',') AS physiciantypeid
from     patientphysicians
group by patientid

其次,程序的SQL也需要修正。您似乎想列出与某个特定患者相关的所有医生的详细信息。为此目的,加入视图是没有意义的,因为视图仅返回患者的一条记录,并将医生类型聚合为逗号分隔列表。这对于您在过程中使用的SQL没有用,您希望为每位医生提供单独的记录。因此,从中移除视图,然后返回每位医生的医生类型。

除此之外,您应该使用与select列表中相同的 physicianid 进行分组。不要从 p 中的 physicianid 中的select子句中选择 pp 中的 doctorid >

以下是建议的更新:

SELECT     p.physicianid,
           p.physiciantypeid,
           p.firstname,
           p.lastname,
           p.dob,
           p.mobile,
           p.officephone,
           p.address1,
           p.address2,
           p.city,
           p.stateid,
           p.cid,
           p.zip,
           p.speciality,
           p.about,
           p.imgid
FROM       patientphysicians pp
INNER JOIN physician p 
        ON pp.physicianid = p.physicianid
WHERE      pp.patientid = patientid /* the argument */
GROUP BY   p.physicianid

请注意,在应用适当的缩进时,更有助于理解代码。