错误代码:1055。SELECT列表的表达式#1不在GROUP BY子句中,并且包含未聚合的列

时间:2018-08-15 09:34:05

标签: mysql

试图更多地了解以下错误:

“错误代码:1055。SELECT列表的表达式#1不在GROUP BY子句中,并且包含未聚合的列'companydb.e.dno',该列在功能上不依赖于GROUP BY子句中的列;这与sql_mode =不兼容only_full_group_by“

my data set

my resulting table after join =>使用,从员工,部门中选择dno,dnumber,dname,fname,ssn,其中dno = dnumber按dname排序;

据我了解,我可以在select子句中使用那些对于使用group by和Have子句进行过滤的集合唯一的列。所以,这是我的困惑。

以下查询(查找员工人数最少的部门)失败,并出现上述错误:

select **dno**
from employee e, department d 
where e.dno=d.dnumber 
group by **dname** having count(ssn) =
     (select min(mycount) 
      from (select count(ssn) as mycount 
            from employee
            group by dno
           ) mytable
     );

但是下面的查询(对于相同的要求)是成功的:

select **dname**
from employee e, department d 
where e.dno=d.dnumber 
group by **dno** having count(ssn) =
     (select min(mycount) 
      from (select count(ssn) as mycount 
            from employee
            group by dno
           ) mytable
     );

从数据集中,您可以了解在by by之前形成的每个组中的dno和dname是唯一的。那么,我可以选择dno和group by dname一起选择dname吗?

2 个答案:

答案 0 :(得分:0)

如果选择列表中的值是明确,MySQL必须先确定,然后再查看实际数据。这是语法错误,而不是值错误。

根据documentation,Mysql将

  

拒绝查询,其中选择列表,HAVING条件或ORDER BY列表引用的是未聚合的列,这些列既未在GROUP BY子句中命名,也未在功能上依赖于(唯一确定)GROUP BY列。

“在功能上取决于列的分组”是一种奇特的说法:如果您知道分组列的值,那么您毫无疑问会知道选择列表中引用的值。这就是您的意思:您假设,如果您知道dname,那么您无疑会知道dno

但是目前,您的数据模型中没有任何东西可以阻止您给每个部门起相同的名字。只要您能够做到这一点,MySQL就必须为此做好准备(并且必须拒绝您的查询,因为它不检查数据)。要告诉MySQL您不会/不能这样做,可以将dname定义为unique not null。然后dnumber“唯一确定” dno / dname,并且select dno ... group by dname应该起作用。

您的第二个查询select dname ... group by dno(相当于select dname ... group by dnumber)之所以起作用,是因为它是主键(因此行中的每个值在功能上都依赖于它):如果您知道{ {1}} / dnumber,对于dno的值没有任何歧义。

如果您不想添加该约束(但100%确定已满足 ,包括dname),也可以将null替换为{{ 1}}。如果select dno ... group by dname实际上 与您假设的一样明确,则这在逻辑上是等效的(因为每个select dno ... group by dno都有一个dname,每个dname都有一个{ {1}})。由于相同的原因,在两种情况下都可以简单地使用dno。另外,您也可以使用dno,对结果也没有影响,因为dname的唯一值就是该值。

所有这些方法都用于通知MySQL在任何情况下都可以在查看实际数据之前找到一个明确的值。如果您的假设正确,那么它不会改变结果(尽管可能会影响执行计划)。如果更改结果集,则您的假设是不正确的。

答案 1 :(得分:0)

探索了其他选项,并提出了以下建议:

以下规则适用于要在选择列表中使用的列(分组列除外):

情况1:选择涉及单个表

1)按col1分组=> col1必须是唯一且不能为null或相应表的主键列

从雇员...按lname分组选择super_ssn =>错误

从雇员...按lname分组选择super_ssn(如果lname是唯一的不为null)=>成功

从部门...按dname分组选择mgr_start_date =>错误

从部门...按dname分组选择mgr_start_date(如果dname是唯一的不为null)=>成功

2)按col1,col2分组... => col1,col2 ...之一应该是唯一的,不能为null或对应表的主键列

从雇员中选择super_ssn ...按性别分组,姓氏=>错误

从雇员...按性别分组,选择super_ssn,lname(如果lname是唯一的,不为null)=>成功

从部门...按mgr_ssn,dname分组选择mgr_start_date ==错误

从部门...按mgr_ssn,dname分组选择mgr_start_date(如果dname是唯一的不为null)=>成功

案例2:选择涉及多个表

1)按col1分组=>如果col1为唯一且不为null或对应表的主键列,则只能在选择列表中使用同一表中的列

从员工,部门中选择super_ssn ...按ssn分组=>成功

从雇员,部门...按dnumber分组选择super_ssn ==错误

从雇员,部门...按dnumber分组选择mgr_start_date ==>成功

从雇员,部门...按ssn分组选择mgr_start_date ==错误

2)按col1,col2分组... =>

a)如果col1 / col2 ...是唯一且不为null或对应表的主键列,则只能将与col1,col2 ...之一相同的表中的列用于选择列表中

从雇员,部门中选择super_ssn ...按ssn,dname分组==成功

从雇员,部门中选择super_ssn ...按lname,dname分组==错误

从雇员,部门...按dnumber,lname分组选择mgr_start_date

从雇员,部门...按dname,lname分组选择mgr_start_date ==错误

b)如果按列分组的组之一是任何表的主表,则可以使用任何tany列。这不适用于主键列分组是联接条件的一部分

例1:ssn即使雇员表的主键列也可以用来选择任何表中的任何列

从部门,员工中选择mgr_start_date ...按ssn分组=>成功

例2:即使部门表的主键列是Dnumber,但由于它是联接条件的一部分,因此不能用于选择任何表中的任何列

从部门,员工中选择super_ssn ...按dnumber分组=>错误