2015-01-01 2 views
1

Представьте таблицу - resume - в базе данных, содержащей документы, и каждый документ содержит много компонентов. Строки в этой таблице может быть либо сам по себе (метаданные для документа) документа или компоненты этого документа:Возвратите все соответствующие строки в Oracle на основе одной строки

row_id name  resume_id last_upd 
1  resume_1    2010-1-1 
2  section_1 1   2008-12-1 
3  section_2 1   2009-6-1 
4  resume_2    2010-1-1 
5  section_1 4   2014-12-30 

В приведенном выше примере, строки 1 и 4 представляют собой документы сами с дополнительными столбцами, содержащими метаданные , а строки 2, 3 и 5 являются компонентами документов, которые могут быть сопоставлены с resume_id.

Что я пытаюсь сделать, это вернуть полный документ (основную запись и компоненты) из этой таблицы, если какая-либо из этих строк (основная запись или компоненты) была обновлена ​​в течение одного года. Если какой-либо элемент документа отредактирован, только эта строка содержит обновленный столбец last_upd.

Вот запрос я построил до сих пор, но это довольно медленно, и я пытаюсь разобраться, как сделать это быстрее:

SELECT meta_data.row_id as "resume_id", 
     meta_data.name as "resume_name", 
     components.name as "component_name" 
FROM 
(
    SELECT DISTINCT(updated_meta_data.row_id) 
    FROM resume updated_meta_data 
    LEFT JOIN resume updated_components ON updated_components.resume_id = updated_meta_data.row_id 
    WHERE ((updated_components.last_upd > (SYSDATE - 365)) or (updated_meta_data.last_upd > (SYSDATE - 365))) 
) updated_resumes 
LEFT JOIN resume meta_data ON updated_resumes.row_id = meta_data.row_id 
LEFT JOIN resume components ON components.resume_id = meta_data.row_id 

Я думаю, что мой запрос работает, но в случае, если это Безразлично «т, или если это не ясно, что я пытаюсь сделать, мой запрос должен возвращать:

resume_id resume_name component_name 
4   resume_2  
4   resume_2  section_1 
+1

Возможно, вы захотите подумать о переименовании своих столбцов, чтобы указать отношения между родителем и ребенком? row_id можно путать с Oracle rowid. – OldProgrammer

ответ

0

Вы можете упростить запрос, предполагая, что resume_id является недействительным, если оно является основной записи документа. В противном случае используйте выражение CASE.

SELECT meta_data.row_id as "resume_id", 
     meta_data.name as "resume_name", 
     components.name as "component_name" 
FROM 
(
    SELECT DISTINCT coalesce(resume_id, row_id) row_id 
    FROM resume 
    WHERE last_upd > SYSDATE - 365 
) updated_resumes 
INNER JOIN resume meta_data ON updated_resumes.row_id = meta_data.row_id 
LEFT JOIN resume components ON meta_data.row_id = components.resume_id 

Я не уверен, почему вы использовали LEFT JOINs, при необходимости отрегулируйте.

+0

Я использовал левые соединения, потому что строки возобновления метаданных могут существовать даже без строк компонента, и я хочу, чтобы я тоже их захватил. спасибо за помощь здесь! – sepiroth

+0

ОК, я скорректировал запрос соответственно – koriander

1

Следующая должен вернуть все «документы», которые были обновлены в прошлом году:

select coalesce(resume_id, row_id) 
from resume 
group by coalesce(resume_id, row_id) 
having last_upd >= sysdate - 365; 

Чтобы получить полный список компонентов, вы можете использовать join или in или exists. Затем вы можете присоединиться к остальной информации:

select rs.resume_id, r.name as resume_name, c.name as component_name 
from (select coalesce(resume_id, row_id) as theid 
     from resume 
     where last_upd >= sysdate - 365 
     group by coalesce(resume_id, row_id) 
    ) rs left join 
    resume r 
    on rs.theid = r.id left join 
    resume c 
    on rs.theid = rs.resume_id; 
+0

Я не думаю, что подзапрос, который вы написали, работает - я вставил его, заменил переменные на мои и получил ошибку «не GROUP BY expression» – sepiroth

+0

@sepiroth. , , К сожалению, это условие 'having' должно быть' where'. –

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