【问题标题】:avg operation on repeated values对重复值进行平均操作
【发布时间】:2014-07-29 06:32:42
【问题描述】:

我有两张表,员工表和认证表。

认证表包含经认证可驾驶飞机的员工列表。一名员工可能获得了多架飞机的认证,反之亦然。并非所有员工都经过认证。

每个员工都领取薪水。 只有一份薪水,不管有多少认证。

我如何找到至少获得一架飞机认证的员工的平均工资?

我的问题是,

SELECT AVG(SALARY) FROM EMPLOYEE E, CERTIFIED C WHERE E.EID=C.EID;

如果员工获得两架飞机的认证,这包括两倍的薪水。所以 AVG(salary) 给出了错误的值。

我是新手,如果我的问题看起来太简单,我深表歉意。帮忙?

【问题讨论】:

  • 您使用的是哪个 DBMS?给定员工的每个重复行的薪水是否相同?

标签: sql select


【解决方案1】:

您想在这里进行半连接。您可以使用 IN 谓词来实现它:

SELECT AVG(SALARY)
FROM EMPLOYEE
WHERE EID IN (
             SELECT EID
             FROM CERTIFIED
             )
;

或使用 EXISTS 谓词:

SELECT AVG(e.SALARY)
FROM EMPLOYEE AS e
WHERE EXISTS (
             SELECT *
             FROM CERTIFIED AS c
             WHERE c.EID = e.EID
             )
;

如果CERTIFIED.EID 可以为空并且确实有空值,则 IN 谓词将无法按预期工作,尽管我认为在该表中存储与任何员工无关的证书是不寻常的。

或者,您可以使用正确的连接(我建议您也认真考虑切换到正确的连接语法),只需要连接到一组 distinct EID 派生值从CERTIFIED,而不是直接到CERTIFIED。对于派生表,您可以使用 DISTINCT:

SELECT AVG(e.SALARY)
FROM EMPLOYEE AS e
INNER JOIN (
           SELECT DISTINCT EID
           FROM CERTIFIED
           ) AS c
    ON e.EID = c.EID
;

或分组:

SELECT AVG(e.SALARY)
FROM EMPLOYEE AS e
INNER JOIN (
           SELECT EID
           FROM CERTIFIED
           GROUP BY EID
           ) AS c
    ON e.EID = c.EID
;

【讨论】:

  • 我想我更喜欢JOIN 版本。这也是我唯一一次使用DISTINCT,因为没有要计算的总和。
  • 是的,在这种情况下,DISTINCT 也非常适合可读性(好吧,无论如何,在我看来)。
【解决方案2】:

如果一个员工只能有一份薪水,我建议

SELECT AVG(e.salary)
FROM employee e
WHERE e.id in (SELECT c.id FROM certified c)

这样可以确保每个 eid 被占用一次。我仍然不明白认证表在这里做什么。您是否只需要获得飞行认证的员工的薪水?

【讨论】:

  • 平均工资每位员工不会受此联接影响,但总体平均工资(这是 OP 所追求的)可能会受到影响。
猜你喜欢
  • 1970-01-01
  • 2018-08-29
  • 2021-07-31
  • 2018-09-20
  • 2020-12-26
  • 2015-06-02
  • 1970-01-01
  • 1970-01-01
  • 2018-04-28
相关资源
最近更新 更多