是否可以将这些查询压缩成一个?

时间:2010-08-10 11:48:36

标签: mysql

我有两个表,其中一个表包含引用另一个表的记录:

Goal
  id (int)
  name (text)
  value_mask (text)

GoalStatus
  id (int)
  goal (int)
  created (datetime)
  value (text)

Goal.id == GoalStatus.goal

我想做的是,从GoalStatus表中为目标中的每条记录提取最新记录。目前,我知道如何执行此操作的唯一方法是对Goal(伪代码)中的每条记录单独进行查询:

goals = db.query("SELECT * FROM Goal")

foreach (goals as goal):
    goalStatus = db.query("
        SELECT * FROM GoalStatus
        WHERE goal = " + goal.id + "
        ORDER BY created DESC
        LIMIT 1
    ")

有没有一种方法可以解决这个问题,所以我不会对每个目标进行额外的查询?

3 个答案:

答案 0 :(得分:1)

select 
      g.*,
      gs.id GoalStatusID,
      gs.created,
      gs.value
   from 
      goal g inner join goalstatus gs
          on g.id = gs.goal
   where 
      gs.created in 
          ( select max( gs2.created )
               from goalstatus gs2
               where g.id = gs2.goal )

答案 1 :(得分:1)

这是每组最大的问题。这是一件非常普遍的事情,想要做到这一点,SQL并不容易,所以它会被问到很多。

Here's a summary您可以采取的方法。它们将具有不同的性能属性,并且当有两行与最大值共享相同的值时,它们的行为会有所不同。

作为默认的第一种方法,我倾向于使用null-left-join而不是子查询:

SELECT ...
FROM Goal
JOIN GoalStatus AS Gs0 ON Gs0.goal=Goal.id
LEFT JOIN GoalStatus AS Gs1 ON Gs1.goal=Goal.id AND Gs1.created>Gs0.created
WHERE Goal.id=(someid)
AND Gs1.id IS NULL

也就是说,连接没有其他行具有更大created值的行。

答案 2 :(得分:0)

您可以加入GoalStatus,其中没有其他具有相同目标ID且具有更长创建日期的目标状态。

SELECT * 
FROM Goal 
    INNER JOIN GoalStatus on Goal.GoalId=GoalStatus.GoalId 
WHERE Not Exists(SELECT * 
                 FROM GoalStatus innerGs 
                 WHERE innerGs.GoalId=Goal.GoalId 
                     and innerGs.created > GoalStatus.created)

非常丑陋,可能表现不佳,但我能想到的只有。