2014-11-19 5 views
0

У меня есть две таблицы:Postgresql: выберите значение MAX из двух соединяемых таблиц

tbl_status: 
    id 
    status_code 
    month_digest_id 
    project_id 

tbl_project 
    id 
    name 

tbl_month_digest: 
    id 
    month_ts 

У меня есть проект. Каждый проект имеет статус нулевого или более месяцев (хранится в tbl_month_digest). Учитывая список идентификаторов проектов, мне нужно получить последний объект статуса.

У меня возникли проблемы с этим. В MySQL я мог выбирать из соединения tbl_month_digest и tbl_status и добавлять having tbl_month_digest.month_ts = max(tbl_month_digest.month_ts). Postgres настаивает, что я добавляю tbl_month_digest.month_ts в группу, которая не имеет желаемого эффекта.

Возможно ли получить последний статус для списка проектов в одном запросе SQL в postgresql?

Пример данных и ожидаемый результат:

tbl_month_digest: 
id month_ts 
1 2014-05-01 
2 2014-06-01 
3 2014-07-01 

tbl_project: 
id name 
90 'Foundation' 
91 'Testing' 
92 'Examination' 

tbl_status: 
id project_id month_digest_id status_code 
1 90   1    'on_track' 
2 90   2    'on_track' 
3 90   3    'late' 
4 91   1    'late' 
5 91   2    'unknown' 
6 91   3    'unknown' 
7 92   1    'late' 
8 92   2    'late' 
9 92   3    'on_track' 

Данный проект идентификаторами 90 и 91, я хотел бы получить

project_id latest_status 
90   'late' 
92   'on_track' 

ответ

1

Я не уверен, почему самый последний статус для 91 будет on_track. Но вы можете делать то, что хотите, с помощью оконных функций.

Я предполагаю, что вам даже не нужна таблица month_digest, потому что идентификаторы обычно будут вовремя.

select s.project_id, s.status as latest_status 
from (select s.*, 
      row_number() over (partition by project_id order by month_digest_id desc) as seqnum 
     from tbl_status s 
     where project_id in (90, 91) 
    ) 
where seqnnum = 1; 

Вы можете сделать в основном ту же самую вещь с более join:

select s.project_id, s.status as latest_status 
from (select s.*, 
      row_number() over (partition by project_id order by md.month_ts desc) as seqnum 
     from tbl_status s join 
      tbl_month_digest md 
      on s.month_digest_id = md.id 
     where project_id in (90, 91) 
    ) 
where seqnnum = 1; 

EDIT:

Actually, в Postgres, вы можете использовать distinct on:

 select distinct on(s.project_id) s.project_id, s.status as latest_status 
     from tbl_status s join 
      tbl_month_digest md 
      on s.month_digest_id = md.id 
     where s.project_id in (90, 91) and s.status <> 'unknown' 
     order by s.project_id, md.month_ts desc; 

Я m не уверен, что вы хотите делать с неизвестными состояниями. Это просто отфильтровывает их.

+0

Извините. Я хотел поставить '92' = 'on_track'. Из-за деталей в реальной реализации я не могу полагаться на id месяца_digest в качестве прокси-сервера для 'month_ts' - мне нужно посмотреть фактический месяц. –

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