Reputation: 51
I have a loan table and a properties table. One to many relationship. If the loan contains more than one property, I have to only retrieve the property that has the highest appraisal value.
The following query
SELECT l.loan_id,p_count
FROM loans lo
JOIN
(SELECT loan_id, MAX(appraised_value) AS val
COUNT(property_id) AS p_count
FROM properties
GROUP BY loan_id) AS pc ON pc.loan_id = lo.id
gives me the output
loan_id val p_count
817 914,000 2
But if I attempt to retrieve additional attributes (e.g type, address) from the properties table, I get records all the properties for that loan (2, in this case). I wrote this query
SELECT l.loan_id,p_count
FROM loans lo
JOIN
(SELECT loan_id, MAX(appraised_value), type, address AS val
COUNT(property_id) AS p_count
FROM properties
GROUP BY loan_id) AS pc ON pc.loan_id = lo.id
to get the following output:
loan_id val p_count type address
817 800,000 2 duplex 123 main street
817 914,000 2 triplex 234 cedar avenue
How can I get the following output for the highest appraised value?
loan_id val p_count type address
817 914,000 2 triplex 234 cedar avenue
Upvotes: 0
Views: 2604
Reputation: 1171
Try this out:
proc sql;
select a.loan_id,p1.val,p1.p_count,p2.type,p2.address
from
loans l
left join
(select loan_id,max(appraised_value) as val,count(propoerty_id) as p_count
from propoerties
group by loan_id) p1
on l.id = p1.loan_id
left join
propoerties p2
on p1.loan_id = p2.loan_id and p1.val=p2.appraised_value;
Let me know in case you have any different requirement.
Upvotes: 0
Reputation:
You can use window functions to calculate the count of properties per loan and the highest value in the same query:
SELECT lo.id, pc.p_count, pc.appraised_value, pc.type, pc.address
FROM loans lo
JOIN (
SELECT loan_id,
appraised_value,
type,
address,
count(*) over (partition by loan_id) AS p_count,
dense_rank() over (partition by loan_id order by appraised_value desc) as rnk
FROM properties
) AS pc ON pc.loan_id = lo.id and rnk = 1;
As Josh commented, if two properties have the same highest appraised_value, both will be listed. If you don't want that, use row_number()
instead of dense_rank()
.
Upvotes: 4
Reputation: 5146
You can use the ROW_NUMBER()
analytic function to rank the records:
select
x.loan_id
,x.val
,x.p_count
,x.type
,x.address
from (
select
l.loan_id
,p.appraised_value as val
,p.type
,p.address
,row_number() over (partition by l.loan_id order by p.appraised_value desc) as ranker
,count(1) over (partition by l.loan_id) as p_count
from loans l
left join properties p
on l.loan_id = p.loan_id
) x
where x.ranker = 1
Upvotes: 0