LEFT OUTER JOIN有条件(在哪里,按顺序)?

时间:2011-08-10 18:26:13

标签: mysql sql postgresql ruby-on-rails-3.1

我正在使用MySql(本地)和Postgresql(Heroku)数据库开发Rails3项目。
我需要在LEFT OUTER JOIN上设置条件,但我不知道如何。

我有2个表TRAININGS和TRAINING_HISTORIES 我想检索TRAININGS的所有记录,并添加TRAINING_HISTORIES的最后一个有效(又名完成)相关记录。

表培训

id  name  order_by
5   A     1  
6   B     2  
7   C     3

表TRAINING_HISTORIES

id  training_id finished_at score
43  5           2011-06-06  10
44  5           null        null
45  6           2011-07-07  11
46  6           2011-08-08  14
47  6           null        null
48  6           2011-09-09  18
49  6           null        null
50  7           null        null
51  7           2011-10-10  19

这是我的SQL查询:

SELECT tc.id, tc.name, tc.order, 
th.id as history_id, th.finished_at, th.score
FROM trainings tc
LEFT OUTER JOIN training_histories th ON th.training_id = tc.id
WHERE tc.id > 4
AND tc.id < 8
GROUP BY tc.id
ORDER BY tc.order_by ASC, tc.id ASC

结果我有:

id  name  order history_id  finished_at score
5   A     1     43          2011-06-06  10
6   B     2     45          2011-07-07  11
7   C     3     50          null        null
  • 查询检索每个联接的第一个training_history

结果我需要:

id  name  order history_id  finished_at score
5   A     1     43          2011-06-06  10
6   B     2     48          2011-09-09  18
7   C     3     51          2011-10-10  19
  • 在这种情况下:这是最后一次完成的training_history谁被检索...

任何建议真的很感激!

谢谢

编辑:如果有人可以在Rails部分回答,那也可能很棒;-)
How to Convert SQL Query to Rails Active Record Query?

3 个答案:

答案 0 :(得分:8)

尝试此查询,它将为您提供每个培训和每个培训的最新培训历史记录:

SELECT tc.id, tc.name, tc.order, 
th.id as history_id, th.finished_at, th.score
FROM trainings tc
LEFT OUTER JOIN training_histories th ON th.training_id = tc.id 
    and th.id =
    (SELECT th1.id from training_histories th1 where th1.training_id = tc.id
     and th1.finished_at is not null
     order by th1.finished_at desc limit 1)
WHERE tc.id > 4
AND tc.id < 8
GROUP BY tc.id
ORDER BY tc.order_by ASC, tc.id ASC

答案 1 :(得分:1)

我很确定你能做到

SELECT tc.id, tc.name, tc.order, 
th.id as history_id, th.finished_at, th.score
FROM trainings tc
LEFT OUTER JOIN (SELECT id, training_id, MAX(finished_at) as finished_at, score 
    FROM training_histories GROUP BY training_id) th ON th.training_id = tc.id
WHERE tc.id > 4
AND tc.id < 8
GROUP BY tc.id
ORDER BY tc.order_by ASC, tc.id ASC

答案 2 :(得分:-2)

同样在finished_at not null的where条件检查中添加Order by finished_at DESC

SELECT tc.id, tc.name, tc.order, 
th.id as history_id, th.finished_at, th.score
FROM trainings tc
LEFT OUTER JOIN training_histories th ON th.training_id = tc.id
WHERE tc.id > 4
AND tc.id < 8
AND th.finished_at IS NOT NULL
GROUP BY tc.id
ORDER BY tc.order_by ASC, tc.id ASC, th.finished_at DESC