Nice ideas - I work in the insurance industry and use this often to look for out-of-sequence endorsements and transactions. Here's another way to acheive it, without a join.
select personid, version, dedate,
row_number() over (partition by personid order by version) as VersionOrder,
row_number() over (partition by personid order by dedate) as DeOrder,
case when row_number() over (partition by personid order by version) -
row_number() over (partition by personid order by dedate) <> 0 then '1' else '0' end as IsImproper
from personrecord
order by personid, version
Only catch here (and for others) is that both fileds you are comparing over a given personid must be unique...