Reputation: 133
I have 2 tables in my database: da_documents and da_favourites. As you expect da_favourites is the documents added to the favourites list by a user. da_documents stores all the documents available
Each document has key columns: da_doc_id (id for set of documents), da_document_id (unique id for every document), da_version (version of the document).
da_doc_id can be shared between lot of different da_document_ids.
I'm trying to come up with a select statement to show da_doc_id, da_document_id from da_favourites table and also the latest da_document_id for this specific da_doc_id.
Say we added da_document_id 14001 and 14002 to da_favourites but 14003 exists in da_documents I want to be able to see that latest da_document_id next to the da_document_id added to the favourites.
I have came up with a statement that shows documents that have a newer version however I'm unable to show the latest da_document_id for that document.
select da_doc_id, da_document_id
from da_favourites o
where da_document_id !=
(SELECT da_document_id
FROM da_documents d
WHERE da_version IN (SELECT MAX (da_version)
FROM da_documents i
WHERE i.da_doc_id = d.da_doc_id
GROUP BY i.da_doc_id)
AND d.da_doc_id = o.da_doc_id);
@edit
I want to end up with something like this:
da_documents sample data
da_favourites sample data
As you can see version 4 of da_doc_id 14874 exists.
I've finally come up with this. Is there a simpler way of doing it?
SELECT dad.da_doc_id, daf.da_document_id, dad.da_document_id latest_document_id
FROM da_documents dad
JOIN da_favourites daf
ON dad.da_doc_id = daf.da_doc_id
WHERE da_version IN (SELECT MAX (da_version)
FROM da_documents dad2
WHERE dad2.da_doc_id = dad.da_doc_id
GROUP BY dad2.da_doc_id)
AND dad.da_document_id != daf.da_document_id
AND dad.da_doc_id IN (SELECT da_doc_id
FROM da_favourites);
Upvotes: 0
Views: 46
Reputation: 409
If it is used frequently I would create a view
CREATE VIEW vw_doc_version AS
SELECT da_doc_id, MAX(da_version) latest_version
FROM da_documents
GROUP BY da_doc_id
Your sql would then be simple
SELECT f.da_doc_id, f.da_document_id, d.da_document_id AS latest_document_id
FROM da_favourites f
INNER JOIN vw_doc_version dv ON dv.da_doc_id = f.da_doc_id
INNER JOIN da_documents d ON d.da_doc_id = dv.da_doc_id
AND d.da_version = dv.latest_version
Otherwise you could do it with a derived table
SELECT f.da_doc_id, f.da_document_id, d.da_document_id AS latest_document_id
FROM da_favourites f
INNER JOIN (SELECT da_doc_id, MAX(da_version) latest_version
FROM da_documents
GROUP BY da_doc_id) dv
ON dv.da_doc_id = f.da_doc_id
INNER JOIN da_documents d
ON d.da_doc_id = dv.da_doc_id
AND d.da_version = dv.latest_version
or cte
with cte as (SELECT da_doc_id, MAX(da_version) latest_version
FROM da_documents
GROUP BY da_doc_id)
SELECT f.da_doc_id, f.da_document_id, d.da_document_id AS latest_document_id
FROM da_favourites f
INNER JOIN cte dv
ON dv.da_doc_id = f.da_doc_id
INNER JOIN da_documents d
ON d.da_doc_id = dv.da_doc_id
AND d.da_version = dv.latest_version
Excuse any syntax or formatting errors as I don't have an oracle background.
Feedback is welcome.
Edited to include document id of latest version
Upvotes: 1
Reputation: 10701
You may use window functions for this
SELECT o.*, t.da_document_id
FROM da_favourites o
JOIN
(
SELECT i.*, row_number() over (partition by i.da_doc_id order by da_version desc) rn
FROM da_documents i
) t ON t.da_doc_id= o.da_doc_id and
t.rn = 1 and
t.da_document_id != o.t.da_document_id
Upvotes: 0