2010-08-10 4 views
1

У меня есть две таблицы, с одной содержащим записи ссылок другим:Можно ли сконденсировать эти запросы в один?

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

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

Goal.id == GoalStatus.goal 

То, что я хотел бы сделать, это вытащить последнюю запись из таблицы GoalStatus, для каждой записи в цели. На данный момент единственный способ я знаю, как сделать это, сделав отдельный запрос для каждой записи в Цели (псевдокода):

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 
    ") 

есть способ конденсации, поэтому я не делаю дополнительный запрос для каждой цели?

+0

Я думаю, что вы хотите: http://stackoverflow.com/questions/1537606/mysql-group-by-with-top-n-number-of-each-kind –

+0

и еще одна ссылка: go to mysql part http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/ –

ответ

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 значение.

+0

Ссылка была отличной. Я не мог заставить ваш пример работать, но первый метод на этой странице работал для меня - спасибо! – Ross

0

Вы можете присоединиться к 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) 

Очень уродливый и, вероятно, будет работать плохо, но все, что я мог придумать.

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) 
+0

В итоге я использовал что-то похожее на это , – Ross

Смежные вопросы