基于来自另一个表的聚合结果更新表

时间:2015-02-25 17:31:30

标签: mysql sql aggregate-functions

这个想法是我试图以不同的方式更新教师的工资,因为他们是在指导新生,二年级学生,三年级学生还是老年人。应该只应用最高的适用加薪,我收集的是case语句按顺序评估的事实。

我正在使用select语句来计算是否有任何教师指导某一学生分类的情况,如果有,则应用适用的加薪。

update Instructor i
set i.Salary = (
case 
when (0 < (select count(*) from Student s where s.Classification = "Senior" 
    and i.InstructorID = s.MentorID)) then i.Salary * 1.1
when (0 < (select count(*) from Student s where s.Classification = "Junior" 
    and i.InstructorID = s.MentorID)) then i.Salary * 1.08
when (0 < (select count(*) from Student s where s.Classification = "Sohpomore" 
    and i.InstructorID = s.MentorID)) then i.Salary * 1.06
when (0 < (select count(*) from Student s where s.Classification = "Freshman" 
    and i.InstructorID = s.MentorID)) then i.Salary * 1.04
else i.Salary
end);

我写的这个查询没有执行。将select语句放在when中作为比较是否有效?如果是这样,上面的代码有什么问题?或者我是否必须使用某些控制流逻辑将它们移动到where语句?我觉得由于select语句数量很多,这个效率很低。

编辑:这是一些示例数据和预期输出:

Student: MentorID Classification
         100      Sophomore
         101      Junior
         102      Senior
         101      Senior

Instructor: InstructorID Salary
            100          100000 
            101          50000 
            102          80000 
            103          100000 

更新后

Instructor: InstructorID Salary
            100          106000 //*1.06 because mentee is a sophomore
            101          55000  //*1.1 because highest mentee is senior
            102          88000  //*1.1 because mentee is a senior
            103          100000 //No change because no mentees

1 个答案:

答案 0 :(得分:0)

你是对的,运行几个select语句可能效率低下。你可以消除这一点。在进行任何更新之前,我认为我们可以同意至少需要以下内容:

  • 每位指导教师每个分类有多少学生?

让我们考虑以下教师和学生的样本数据集:

| instructorID | name | salary |
+--------------+------+--------+
|       1      | Adam |    1   |
|       2      | Sam  |    1   |
|       3      | John |    1   |
|       4      | Jane |    1   |

| studentID | classification | mentorID |
+-----------+----------------+----------+
|    1      |   Senior       |    1     |
|    2      |   Junior       |    1     |
|    3      |   Sophomore    |    2     |
|    4      |   Freshman     |    2     |
|    5      |   Senior       |    1     |
|    6      |   Freshman     |    3     |
|    7      |   Sophomore    |    1     |

在这种情况下,亚当教高年级,所以他的薪水应该是1.1。 John最多教大二,所以他的薪水是1.06。 Sam最多只教一个新生,所以他的薪水是1.04而Jane没有教过任何人,所以她的薪水最后应该保持1分。

我们可以使用以下聚合找到每位教师的学生人数:

SELECT i.instructorID,
   SUM(s.classification = 'Senior') AS numSeniors,
   SUM(s.classification = 'Junior') AS numJuniors,
   SUM(s.classification = 'Sophomore') AS numSophomores,
   SUM(s.classification = 'Freshman') AS numFreshmen
FROM instructor i
LEFT JOIN student s ON s.mentorID = i.instructorID
GROUP BY i.instructorID;

您可以在update语句中将其用作JOIN,以使用case语句设置值:

UPDATE instructor i
JOIN (mySubquery) tmp ON tmp.instructorID = i.instructorID
SET i.salary = 
   CASE WHEN tmp.numSeniors > 0 THEN (i.salary * 1.1)
   WHEN tmp.numJuniors > 0 THEN (i.salary * 1.08)
   WHEN tmp.numSophomores > 0 THEN (i.salary * 1.06)
   WHEN tmp.numFreshmen > 0 THEN (i.salary * 1.04)
   ELSE i.salary END;

以下是SQL Fiddle示例。