Sql 每个部门的平均工资

Sql 每个部门的平均工资,sql,oracle,Sql,Oracle,我正在做SQL简介,目前正在做这个练习,但我被卡住了 练习: 创建部门名称、经理id、该部门的经理姓名(员工姓氏)以及每个部门的平均工资列表 下面是练习的模式,只是我正在使用的表 CREATE TABLE "EMPLOYEES" ("EMPLOYEE_ID" NUMBER(6,0), "FIRST_NAME" VARCHAR2(20), "LAST_NAME" VARCHAR2(25) CONSTRAINT "EMP_LAST_NAME_NN" NOT NULL ENABLE, "EMAIL"

我正在做SQL简介,目前正在做这个练习,但我被卡住了

练习:

创建部门名称、经理id、该部门的经理姓名(员工姓氏)以及每个部门的平均工资列表

下面是练习的模式,只是我正在使用的表

CREATE TABLE  "EMPLOYEES"
("EMPLOYEE_ID" NUMBER(6,0),
"FIRST_NAME" VARCHAR2(20),
"LAST_NAME" VARCHAR2(25) CONSTRAINT "EMP_LAST_NAME_NN" NOT NULL ENABLE,
"EMAIL" VARCHAR2(25) CONSTRAINT "EMP_EMAIL_NN" NOT NULL ENABLE,
"PHONE_NUMBER" VARCHAR2(20),
"HIRE_DATE" DATE CONSTRAINT "EMP_HIRE_DATE_NN" NOT NULL ENABLE,
"JOB_ID" VARCHAR2(10) CONSTRAINT "EMP_JOB_NN" NOT NULL ENABLE,
"SALARY" NUMBER(8,2),
"COMMISSION_PCT" NUMBER(2,2),
"MANAGER_ID" NUMBER(6,0),
"DEPARTMENT_ID" NUMBER(4,0),
"BONUS" VARCHAR2(5),
 CONSTRAINT "EMP_SALARY_MIN" CHECK (salary > 0) ENABLE,
 CONSTRAINT "EMP_ID_PK" PRIMARY KEY ("EMPLOYEE_ID")
USING INDEX  ENABLE,
 CONSTRAINT "EMP_EMAIL_UK" UNIQUE ("EMAIL")
USING INDEX  ENABLE
);

CREATE TABLE  "DEPARTMENTS"
("DEPARTMENT_ID" NUMBER(4,0),
"DEPARTMENT_NAME" VARCHAR2(30) CONSTRAINT "DEPT_NAME_NN" NOT NULL ENABLE,
"MANAGER_ID" NUMBER(6,0),
"LOCATION_ID" NUMBER(4,0),
 CONSTRAINT "DEPT_ID_PK" PRIMARY KEY ("DEPARTMENT_ID")
USING INDEX  ENABLE
);
这就是我现在拥有的

select  d.department_name, d.manager_id,e.last_name as "manager_name" , 
avg(salary)
from departments d join employees e ON (e.employee_id=d.manager_id)
group by d.department_name,e.last_name, d.manager_id;
我能够生成它要求的所有字段,除了平均值,我通过单独的查询得到了答案

 select department_name, round(avg(salary)) from employees e join 
 departments d ON (e.department_id=d.department_id)
 group by department_name;

在我的一生中,我不知道如何使select语句(它给出了我的平均工资)起作用,我试图使用一个不起作用的子句,因为它限制了它已经给出的内容。希望有人能向我解释我错过了什么。感谢您的回复

因为employees同时引用经理和非经理,而部门有一个经理,所以您必须在同一SQL中将employees表加入到部门中两次。您正在同一sql中查找这两个连接:


此加入将使经理详细信息与部门关联:

departments inner join employees mgrs on departments.manager_id = mgrs.employee_id

此联接将使员工与部门关联

departments inner join employees emps on emps.department_id = departments.department_id

因此,您的最终sql将包含以下内容:

FROM
 departments
 INNER JOIN employees mgrs ON ....
 INNER JOIN employees emps ON ....
WHERE
困惑?考虑另一个与你相关的例子。你有一个住址和一个工作地址。如果它是一个数据库,它可能会有表
persons
address
。它不会有
家庭地址
工作地址
,因为家庭/工作地址只是一个地址。Persons表可能有一个
家庭地址\u id
和一个
工作地址\u id
,但每个列中都有一个不同的id,指向地址中的两个不同的地址行。这意味着没有办法只加入一次地址,同时获得您的工作地址和家庭地址。从逻辑上讲,它不起作用:如果只有一组地址列,它会显示哪些数据-你的工作还是你的家庭?不能在一个单元格中显示两个值,不能。。你必须添加更多的单元格。我们通过以下方式在现有单元格块的右侧添加更多单元格。。。做另一个加入!如果要在选择列表中包含以下列:

person.Name,
homeaddress.Street,
workaddress.Street
然后地址必须加入两次

Person table
------------
Name      Home_Address_Id Work_Address_Id
JohnSmith 1               2

Address table
-------------
ID Building    Street
1  261         Great Hope Street
2  Office2000  Commercial Way
希望你能清楚地看到你的工作和家庭地址是不同的(你在城市工作,住在乡下,好吗?不允许在家工作),所以你不能说:

person p INNER JOIN address a ON p.home_address_id = a.id AND p.work_address_id = a.id
因为当数据库将两个表连接在一起时,在处理ON条件之前,它会将所有行连接到所有行(概念上),然后进行筛选

Persons-Joined-To-Addresses
---------------------------
Name      Home_Address_Id Work_Address_Id ID Building    Street
JohnSmith 1               2               1  261         Great Hope Street
JohnSmith 1               2               2  Office2000  Commercial Way
您可以看到,没有任何行同时满足这两个条件,因为数据库会扫描它生成的行,并测试满足所有ON条件的行:

Does 1=1 and 2=1? No. Do not include the 'JohnSmith 1               2               1  261         Great Hope Street' row
Does 1=2 AND 2=2? No. Do not include the 'JohnSmith 1               2               2  Office2000  Commercial Way' row
如果你两次加入地址,那就不同了:

Persons-Joined-To-Addresses-Joined-To-Addresses-Again
-----------------------------------------------------
Name      Home_Address_Id Work_Address_Id IH BuildingH   StreetH           IW BuildingW   StreetW
JohnSmith 1               2               1  261         Great Hope Street 1  261         Great Hope Street
JohnSmith 1               2               1  261         Great Hope Street 2  Office2000  Commercial Way
JohnSmith 1               2               2  Office2000  Commercial Way    1  261         Great Hope Street
JohnSmith 1               2               2  Office2000  Commercial Way    2  Office2000  Commercial Way
在这4行中,只有一行满足连接条件。以下是数据库执行的测试列表:

Does 1=1 and 2=1? No. Don't include the 'JohnSmith/Great Hope Street/Great Hope Street' row
Does 1=1 and 2=2? YES. Include the 'JohnSmith/Great Hope Street/Commercial Way' row
Does 1=2 AND 2=1? No. Do not include the 'JohnSmith/Commercial Way/Great Hope Street' row
Does 1=2 AND 2=2? No. Do not include the 'JohnSmith/Commercial Way/Commercial Way' row
这两个条件与之前相同,但我已将ID列重命名为IH和IW。条件是家庭地址id=IH和工作地址id=IW。非常重要的是,您要理解上面“a=b和x=y吗?”行中的概念,即我们通过在地址ID上附加“home”或“work”的含义来区别对待地址ID。他们说:

个人。家庭\u地址id=id\u来源于别名为家庭和个人。工作\u地址id=id\u来源于别名为


在将其输入到一个sql中之后,将员工的工资相加就行了。使sur为每个联接使用不同的employees表别名。我打电话给矿山经理和EMP,以便知道数据是“经理级”还是“员工级”


我没有为您写完整的查询,因为这显然是一个家庭作业,但是如果您需要更多帮助,请发表评论:)

这就是您想要的吗

select d.department_name, d.manager_id,e.last_name as "manager_name", avg(salary)
from departments d join employees e ON (e.employee_id=d.manager_id)
group by d.department_name,d.manager_id, e.last_name ;

最好解释一下这有什么不同,以及为什么你认为它可以回答这个问题。它给出了与我相同的答案,只是改变了分组顺序。它没有给出每个部门的平均值。你能给出一个示例答案吗?不走运,还是一样的问题。除了平均水平外,一切都好。不确定它在那里做什么..您使用的是什么数据库服务器?Oracle SQL数据库感谢您的回复顺便说一句:)最初,我确实让d部门的员工加入e ON(e.employee\u id=d.manager\u id)和(e.department\u id=d.department\u id),这给了我相同的答案。但这只是在满足这两个条件的行上加入employees表一次。。。当我说“SQL必须两次连接表”时,我的字面意思是它必须有一个文本,如
department internal join employees mgr on。。。内部加入员工emp ON…
即,如果对“内部加入员工”按Ctrl+F键,则会显示
2次出现的情况
选择d.部门名称、d.经理id、emps.姓氏作为“经理姓名”,从d.部门加入员工emp ON(emps.员工id=d.经理id)加入员工经理(经理部门id=d部门id)按d.部门名称、d.经理id、emps.姓氏分组;同样的答案仔细阅读您的文章;我之所以称员工表为emps代表员工,经理表为经理,是有原因的。您确定您正确地连接了这些表吗?当两次连接一个表时,正确地命名事物非常重要,以避免将自己绑在一起S“WITH”方法为您提供GROUP BY子句的计算结果。如果不使用“WITH”方法将所有数据合并在一起,则只会得到经理的平均工资,这是经理的正常月薪,而不是部门的平均工资。您只能从虚拟机获取部门的平均工资
WITH DINFO AS (SELECT departments.department_name,departments.department_id,departments.manager_id,ROUND(AVG(salary)) AS AVGSAL
FROM departments
INNER JOIN employees ON (employees.department_id = departments.department_id)
GROUP BY departments.department_name,departments.department_id,departments.manager_id
)

SELECT DINFO.department_name,DINFO.manager_id,last_name, DINFO.AVGSAL FROM employees e, DINFO
WHERE e.employee_id = DINFO.manager_id;