Reputation: 9910
I have a table structure, simplified like so:
period_id int
suite_id varchar(20)
suite_status varchar(50)
Each month is assigned to a period id. Each suite has a record for each month (period_id). Suite status's can be either 'Vacant' or 'Active Lease'. I'm trying to write a query that shows the top five deals that have been leased since the 1st of July 2011 that were vacant the longest before they became an active lease but I don't know how to approach this.
My original approach was to rank each lease by the number of periods that it was vacant, like so:
;WITH cte_vacancy_periods AS
(
SELECT lp.suite_id ,
count(lp.period_id) AS 'Periods Vacant'
FROM property.lease_period lp
WHERE lp.suite_status = 'Vacant'
OR
( isnull(lp.suite_status, '') = ''
AND lp.lease_id = 'No Lease' )
GROUP BY
lp.suite_id
ORDER BY count(lp.period_id) desc
)
I was then planning to cross-reference this with the leases made active since period 258 (the 01-July-2011).
Unfortunately this doesn't work in cases where a lease was vacant for two months, then leased for a month then vacant for two more months (showing a total of four months vacant before being leased when it should really be two).
I'm sure this could be done with a partition but I've come up short trying to do this and don't quite understand them. What am I missing in my knowledge for approaching this problem? If I've explained the data poorly so it's hard to understand what I'm trying to do please let me know and I'll elaborate where I can.
Upvotes: 1
Views: 67
Reputation: 86765
Hopefully an approach something like this will help.
I have to admit that I'm not 100% clear on what final result you're looking for, but this should get you a data-set that can answer many quesions similar to yours.
WITH
reformatted_data
AS
(
SELECT
suite_id,
period_id,
CASE
WHEN suite_status = 'Vacant' THEN 0
WHEN lease_id = 'No Lease' AND isnull(suite_status, '') = '' THEN 0
ELSE 1
END as suite_status
FROM
properties.lease_period
)
,
gaps_and_islands
AS
(
SELECT
suite_id,
period_id,
suit_status,
ROW_NUMBER() OVER (PARTITION BY suite_id ORDER BY period_id) AS seq,
ROW_NUMBER() OVER (PARTITION BY suite_id, suite_status ORDER BY period_id) AS seq_status
FROM
reformatted_data
)
SELECT
suite_id,
suit_status,
MIN(period_id) AS first_period_id,
MAX(period_id) AS last_period_id,
MAX(seq) - MIN(seq) AS consecutive_periods
FROM
gaps_and_islands
GROUP BY
suite_id,
suite_status,
seq - seq_status
Upvotes: 1