试图更多地了解以下错误:
“错误代码:1055。SELECT列表的表达式#1不在GROUP BY子句中,并且包含未聚合的列'companydb.e.dno',该列在功能上不依赖于GROUP BY子句中的列;这与sql_mode =不兼容only_full_group_by“
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吗?
答案 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分组=>错误