【问题标题】:Is it possible to condense these queries into one?是否可以将这些查询压缩为一个?
【发布时间】:2010-08-10 11:48:35
【问题描述】:

我有两张表,一张包含引用另一张的记录:

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

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

Goal.id == GoalStatus.goal

我想做的是从 GoalStatus 表中为 Goal 中的每条记录提取最新记录。目前,我知道如何做到这一点的唯一方法是对 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
    ")

有没有办法压缩这个,所以我不会对每个目标进行额外的查询?

【问题讨论】:

标签: mysql


【解决方案1】:

这是每组最多的问题。想要做的事情很常见,但 SQL 并不容易,所以它被问了很多。

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

作为默认的第一种方法,我倾向于使用空左连接而不是子查询:

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】:
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 )

【讨论】:

  • 我最终使用了类似的东西。
【解决方案3】:

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

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)

相当丑陋,可能会表现不佳,但我能想到的。

【讨论】:

    猜你喜欢
    • 2011-06-18
    • 1970-01-01
    • 1970-01-01
    • 2012-01-09
    • 1970-01-01
    • 2022-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多