MySQL替代使用子查询

时间:2013-11-26 19:51:04

标签: mysql sql

所以,假设我有以下表格Person and Wage。这是1-N关系,一个人可以有一个以上的工资。

**Person**
id
name

**Wage**
id
person_id
amount
effective_date

现在,我想查询所有人员及其最新工资的清单。我可以通过执行以下查询来获得结果:

SELECT 
   p.*, 
   (  SELECT w.amount 
      FROM wages a w 
      WHERE w.person_id = p.id 
      ORDER BY w.effective_date 
      LIMIT 1 
   ) as wage_amount,
   (  SELECT w.effective_date 
      FROM wages a w 
      WHERE w.person_id = p.id 
      ORDER BY w.effective_date 
      LIMIT 1 
   ) as effective_date
FROM person as p

问题是,我的查询将有来自不同表的多个子查询。我想让它尽可能高效。是否可以使用更快的子查询并给出相同的结果?

4 个答案:

答案 0 :(得分:1)

子查询可以像Sam S在他的回答中提到的那样是一个很好的解决方案,但它实际上取决于子查询,您正在使用的dbms以及索引。有关子查询与联接的性能的良好讨论,请参阅此问题和答案:Join vs. sub-query

如果性能对您来说是个问题,则必须考虑使用dbms的EXPLAIN命令。它将向您展示如何构建查询以及瓶颈在哪里。根据其结果,您可能会考虑以其他方式重写您的查询。

例如,通常情况下join会产生更好的效果,因此您可以根据以下答案重写查询:https://stackoverflow.com/a/2111420/362298并比较它们的效果。

请注意,创建正确的索引也会产生很大的不同。

希望它有所帮助。

答案 1 :(得分:1)

正确的索引可能会使您的版本高效运行(即wages(person_id, effective_date)上的索引)。

以下使用单个子查询产生相同的结果:

SELECT p.*, w.amount, w.effective_date
from person p left outer join
     (select person_id, max(effective_date) as maxdate
      from wages
      group by personid
     ) maxw
     on maxw.person_id = p.id left outer join
     wages w
     on w.person_id = p.id and w.effective_date = maxw.maxdate;

这个版本可能比上面的版本更好地使用索引:

SELECT p.*, w.amount, w.effective_date
from person p left outer join
     wages w
     on w.person_id = p.id
where not exists (select * from wages w2 where w2.effective_date > w.effective_date);

请注意,当有两个具有相同最长生效日期的“工资”时,这些版本将为一个人返回多行。

答案 2 :(得分:0)

只要确保使用索引,子查询就非常有效。尝试在查询上运行EXPLAIN,看看它是否使用了正确的索引

答案 3 :(得分:0)

  

SELECT p.name,w.amount,MAX(w.effective_date)FROM Person p LEFT JOIN Wage   w ON w.person_id = p.id GROUP BY p.name

我没有测试此查询。