Question

Is there a more elegant way to define the following view? I need to reduce the table to the the most recent contact of type 10 of each company:

CREATE VIEW COMPANY_LAST_ACQ_CONTACT
as
select 
ci.id, ci.company_id, ci.be_user_id, ci.created_datetime, ci.text
from
(select max(id) as id, company_id
from crm_contact
WHERE crm_contact_reason_id = 10
group by company_id
) co
join crm_contact ci on co.company_id=ci.company_id
;

If I was not interested in be_user_id, created_datetime, text it would simplify as:

CREATE VIEW COMPANY_LAST_ACQ_CONTACT
as
select max(id) as id, company_id
from crm_contact
WHERE crm_contact_reason_id = 10
group by company_id;

There seems to be everything fine with the first view as long as I don't join it with a specific complicated select - the query then hangs/runs forever (at least longer than 20 minutes). This doesn't happen if I join the second view version - this time the query returns the result instantly. I even tried to join the second view with crm_contact again in the complicated select to get the three columns (be_user_id, created_datetime, text) and it runs fast.

Was it helpful?

Solution

You still need a subquery, but analytic functions are a bit more elegant:

CREATE VIEW COMPANY_LAST_ACQ_CONTACT as
    select id, company_id, be_user_id, created_datetime, text
    from (select ci.id, ci.company_id, ci.be_user_id, ci.created_datetime, ci.text,
                 max(id) over (partition by company_id) as maxid
          from crm_contact
         ) c
    where id = maxid;

Another efficient way to write the query -- if you have in index on company_id, id is to use not exists:

select ci.id, ci.company_id, ci.be_user_id, ci.created_datetime, ci.text
from crm_contact c
where not exists (select 1` from crm_contact cc on c.company_id = cc.company_id and cc.id > id);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top