LEFT OUTER JOIN with conditions (where, order by)?

时光怂恿深爱的人放手 提交于 2019-12-12 09:39:43

问题


I'm working on a Rails3 project with MySql (local) and Postgresql (Heroku) databases.
I need to put conditions on a LEFT OUTER JOIN but I don't know how.

I have 2 tables TRAININGS and TRAINING_HISTORIES.
I want to retrieve all the records of TRAININGS and add the last valid (aka finished) associated record of TRAINING_HISTORIES.

table TRAININGS

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

table 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

Here's my SQL query :

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

RESULTS I HAVE :

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
  • The query retrieve the first training_history for each join

RESULTS I NEED :

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
  • In this scenario : it's the last finished training_history who's retrieved...

Any suggestions really appreciated !

Thank you

EDIT: If someone can answer on the Rails part, it could be great too ;-)
How to Convert SQL Query to Rails Active Record Query?


回答1:


Try this Query, it would give you each training and the most recent training history for each one:

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



回答2:


I'm quite sure you can do

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



回答3:


Also in the where condition check for finished_at not null and add 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


来源:https://stackoverflow.com/questions/7015839/left-outer-join-with-conditions-where-order-by

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!