Shasti
Shasti

Reputation: 45

Use of MAX function in SQL query to filter data

The code below joins two tables and I need to extract only the latest date per account, though it holds multiple accounts and history records. I wanted to use the MAX function, but not sure how to incorporate it for this case. I am using My SQL server.

Appreciate any help !

select 
    PROP.FileName,PROP.InsName, PROP.Status,
    PROP.FileTime, PROP.SubmissionNo, PROP.PolNo, 
    PROP.EffDate,PROP.ExpDate, PROP.Region,  
    PROP.Underwriter, PROP_DATA.Data , PROP_DATA.Label
from
    Property.dbo.PROP 
inner join 
    Property.dbo.PROP_DATA on Property.dbo.PROP.FileID = Actuarial.dbo.PROP_DATA.FileID
where 
    (PROP_DATA.Label in ('Occupancy' , 'OccupancyTIV')) 
    and (PROP.EffDate >= '42278' and PROP.EffDate <= '42643')
    and (PROP.Status = 'Bound')
    and (Prop.FileTime = Max(Prop.FileTime))
order by
    PROP.EffDate DESC 

Upvotes: 0

Views: 508

Answers (3)

Christian Bohli
Christian Bohli

Reputation: 341

Not tested

with temp1 as
(
select foo
from bar
whre xy = MAX(xy)
)
                select PROP.FileName,PROP.InsName, PROP.Status,
                 PROP.FileTime, PROP.SubmissionNo, PROP.PolNo, 
                 PROP.EffDate,PROP.ExpDate, PROP.Region,  
                 PROP.Underwriter, PROP_DATA.Data , PROP_DATA.Label

                from Actuarial.dbo.PROP 
                    inner join temp1 t
                    on Actuarial.dbo.PROP.FileID = t.dbo.PROP_DATA.FileID

                    ORDER BY PROP.EffDate DESC 

Upvotes: -2

Craig Tullis
Craig Tullis

Reputation: 10507

Using straight SQL, you can use a self-join in a subquery in your where clause to eliminate values smaller than the max, or smaller than the top n largest, and so on. Just set the number in <= 1 to the number of top values you want per group.

Something like the following might do the trick, for example:

select
    p.FileName
    , p.InsName
    , p.Status
    , p.FileTime
    , p.SubmissionNo
    , p.PolNo
    , p.EffDate
    , p.ExpDate
    , p.Region
    , p.Underwriter
    , pd.Data
    , pd.Label
from Actuarial.dbo.PROP p
inner join Actuarial.dbo.PROP_DATA pd
    on p.FileID = pd.FileID
where (
    select count(*)
    from Actuarial.dbo.PROP p2
    where p2.FileID = p.FileID
    and p2.EffDate <= p.EffDate
    ) <= 1
and (
    pd.Label in ('Occupancy' , 'OccupancyTIV')
    and p.Status = 'Bound'
)
ORDER BY p.EffDate DESC 

Have a look at this stackoverflow question for a full working example.

Upvotes: 1

Hambone
Hambone

Reputation: 16397

Assuming your DBMS supports windowing functions and the with clause, a max windowing function would work:

with all_data as (
  select
   PROP.FileName,PROP.InsName, PROP.Status,
   PROP.FileTime, PROP.SubmissionNo, PROP.PolNo, 
   PROP.EffDate,PROP.ExpDate, PROP.Region,  
   PROP.Underwriter, PROP_DATA.Data , PROP_DATA.Label,
   max (PROP.EffDate) over (partition by PROP.PolNo) as max_date

  from Actuarial.dbo.PROP 
      inner join Actuarial.dbo.PROP_DATA 
      on Actuarial.dbo.PROP.FileID = Actuarial.dbo.PROP_DATA.FileID
  where (PROP_DATA.Label in ('Occupancy' , 'OccupancyTIV')) 
      and (PROP.EffDate >= '42278' and PROP.EffDate <= '42643')
      and (PROP.Status = 'Bound')
      and (Prop.FileTime = Max(Prop.FileTime))
)
select
  FileName, InsName, Status, FileTime, SubmissionNo,
  PolNo, EffDate, ExpDate, Region, UnderWriter, Data, Label
from all_data
where EffDate = max_date
ORDER BY EffDate DESC 

This also presupposes than any given account would not have two records on the same EffDate. If that's the case, and there is no other objective means to determine the latest account, you could also use row_numer to pick a somewhat arbitrary record in the case of a tie.

Upvotes: 2

Related Questions