Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2005 Forums
 Transact-SQL (2005)
 Missing months, filling in gaps

Author  Topic 

duhaas
Constraint Violating Yak Guru

310 Posts

Posted - 2011-02-07 : 21:05:04
I'm starting with the following:

select r.Accountnumber,investmentclass,date
from ror..ror r
where r.accountnumber in (select distinct p.portfolio
from midba..performcompletelogmessage l
left join portfolio p
on p.portfolio = substring(l.messagefinal, 36, 11)
where message_type_id = 6055
and p.id is not null
and effective_date_started = '2011-02-04 17:02:45.000')
order by r.accountnumber,
r.date


I'm trying to find gaps that exist with accounts and dates, for example:

Accountnumber investmentclass date
9841B082000 5 2005-12-31 00:00:00.000
9841B082000 2 2005-12-31 00:00:00.000
9841B082000 3 2005-12-31 00:00:00.000
9841B082000 1 2005-12-31 00:00:00.000
9841B082000 4 2005-12-31 00:00:00.000
9841B082000 0 2005-12-31 00:00:00.000
9841B082000 5 2007-02-28 00:00:00.000
9841B082000 0 2007-02-28 00:00:00.000

The result set will contain various account numbers with varying degrees of gaps. The gaps I want to identify by showing a month end date of the gap along with a way to indicate the missing month while displaying the entire result set. For example:

9841B082000 0 2005-12-31 00:00:00.000
9841B082000 0 2006-01-31 00:00:00.000 MISSING
and so on
9841B082000 5 2007-02-28 00:00:00.000

djorre
Yak Posting Veteran

94 Posts

Posted - 2011-02-08 : 04:30:23
Create a table with all month endings and cross join that table with the accountnumbers as tblAllAccount_Months.
Then do a tblAllAccount_Months left join 'your query' and replace your date-nulls by 'missing'?
Go to Top of Page

duhaas
Constraint Violating Yak Guru

310 Posts

Posted - 2011-02-08 : 09:51:57
quote:
Originally posted by djorre

Create a table with all month endings and cross join that table with the accountnumbers as tblAllAccount_Months.
Then do a tblAllAccount_Months left join 'your query' and replace your date-nulls by 'missing'?


thanks for the followup, a bit of new territory for me here, can you help out with the following as I appear to be missing something:

select r.*,
d.end_of_month_date
from #date d
cross join ror..ror r
where d.end_of_month_date = r.date and
r.accountnumber in (select distinct p.portfolio
from midba..performcompletelogmessage l
left join portfolio p
on p.portfolio = substring(l.messagefinal, 36, 11)
where message_type_id = 6055
and p.id is not null
and effective_date_started = '2011-02-04 17:02:45.000')
--and d.end_of_month_date is null
order by r.accountnumber,r.date


#date is made up of all distinct month end dates
Go to Top of Page

djorre
Yak Posting Veteran

94 Posts

Posted - 2011-02-08 : 10:10:22
something like

select 
q.accountnumber
, q.end_of_month_date
, isnull(cast(t.date as varchar(100)), 'missing')
from
(select distinct d.end_of_month_date, r.accountnumber from #date d cross join (select distinct accountnumber from ror..ror)r) as q
left join
ror..ror as t
on q.accountnumber = t.accountnumber and q.end_of_month_date = t.date
where q.accountnumber in ...
order by q.accountnumber, q.date


or without the #date table, if all dates would be end of month dates:

select 
q.accountnumber
, q.end_of_month_date
, isnull(cast(t.date as varchar(100)), 'missing')
from
(select distinct d.end_of_month_date, r.accountnumber from (select distinct date as end_of_month_date from ror) as d cross join (select distinct accountnumber from ror..ror)as r) as q
left join
ror..ror as t
on q.accountnumber = t.accountnumber and q.end_of_month_date = t.date
where q.accountnumber in ...
order by q.accountnumber, q.date
Go to Top of Page

duhaas
Constraint Violating Yak Guru

310 Posts

Posted - 2011-02-08 : 10:23:59
quote:
Originally posted by djorre

something like

select 
q.accountnumber
, q.end_of_month_date
, isnull(cast(t.date as varchar(100)), 'missing')
from
(select distinct d.end_of_month_date, r.accountnumber from #date d cross join (select distinct accountnumber from ror..ror)r) as q
left join
ror..ror as t
on q.accountnumber = t.accountnumber and q.end_of_month_date = t.date
where q.accountnumber in ...
order by q.accountnumber, q.date


or without the #date table, if all dates would be end of month dates:

select 
q.accountnumber
, q.end_of_month_date
, isnull(cast(t.date as varchar(100)), 'missing')
from
(select distinct d.end_of_month_date, r.accountnumber from (select distinct date as end_of_month_date from ror) as d cross join (select distinct accountnumber from ror..ror)as r) as q
left join
ror..ror as t
on q.accountnumber = t.accountnumber and q.end_of_month_date = t.date
where q.accountnumber in ...
order by q.accountnumber, q.date




your a saint, you've save some folks a great deal of time, thanks again
Go to Top of Page

duhaas
Constraint Violating Yak Guru

310 Posts

Posted - 2011-02-08 : 10:54:02
quote:
Originally posted by duhaas

quote:
Originally posted by djorre

Create a table with all month endings and cross join that table with the accountnumbers as tblAllAccount_Months.
Then do a tblAllAccount_Months left join 'your query' and replace your date-nulls by 'missing'?


thanks for the followup, a bit of new territory for me here, can you help out with the following as I appear to be missing something:

select r.*,
d.end_of_month_date
from #date d
cross join ror..ror r
where d.end_of_month_date = r.date and
r.accountnumber in (select distinct p.portfolio
from midba..performcompletelogmessage l
left join portfolio p
on p.portfolio = substring(l.messagefinal, 36, 11)
where message_type_id = 6055
and p.id is not null
and effective_date_started = '2011-02-04 17:02:45.000')
--and d.end_of_month_date is null
order by r.accountnumber,r.date


#date is made up of all distinct month end dates



one other quick question, is it possible to only have it show me the first month forward for an account and whats missing after its initial month? right now, it goes back to the first month end date available for all accounts in ror. for example:

accountnumber end_of_month_date (No column name)
9841B082000 2003-06-30 00:00:00.000 missing
9841B082000 2003-07-31 00:00:00.000 missing
9841B082000 2003-08-31 00:00:00.000 missing
9841B082000 2003-09-30 00:00:00.000 missing
9841B082000 2003-10-31 00:00:00.000 missing
9841B082000 2003-11-30 00:00:00.000 missing
9841B082000 2003-12-31 00:00:00.000 missing
9841B082000 2004-01-31 00:00:00.000 missing
9841B082000 2004-02-29 00:00:00.000 Feb 29 2004 12:00AM
9841B082000 2004-02-29 00:00:00.000 Feb 29 2004 12:00AM
9841B082000 2004-02-29 00:00:00.000 Feb 29 2004 12:00AM
9841B082000 2004-02-29 00:00:00.000 Feb 29 2004 12:00AM
9841B082000 2004-02-29 00:00:00.000 Feb 29 2004 12:00AM
9841B082000 2004-02-29 00:00:00.000 Feb 29 2004 12:00AM

I really only want it to show me from 2004-02-29 forward in this accounts case, each account would be different
Go to Top of Page

duhaas
Constraint Violating Yak Guru

310 Posts

Posted - 2011-02-08 : 11:14:11
quote:
Originally posted by duhaas

quote:
Originally posted by duhaas

quote:
Originally posted by djorre

Create a table with all month endings and cross join that table with the accountnumbers as tblAllAccount_Months.
Then do a tblAllAccount_Months left join 'your query' and replace your date-nulls by 'missing'?


thanks for the followup, a bit of new territory for me here, can you help out with the following as I appear to be missing something:

select r.*,
d.end_of_month_date
from #date d
cross join ror..ror r
where d.end_of_month_date = r.date and
r.accountnumber in (select distinct p.portfolio
from midba..performcompletelogmessage l
left join portfolio p
on p.portfolio = substring(l.messagefinal, 36, 11)
where message_type_id = 6055
and p.id is not null
and effective_date_started = '2011-02-04 17:02:45.000')
--and d.end_of_month_date is null
order by r.accountnumber,r.date


#date is made up of all distinct month end dates



one other quick question, is it possible to only have it show me the first month forward for an account and whats missing after its initial month? right now, it goes back to the first month end date available for all accounts in ror. for example:

accountnumber end_of_month_date (No column name)
9841B082000 2003-06-30 00:00:00.000 missing
9841B082000 2003-07-31 00:00:00.000 missing
9841B082000 2003-08-31 00:00:00.000 missing
9841B082000 2003-09-30 00:00:00.000 missing
9841B082000 2003-10-31 00:00:00.000 missing
9841B082000 2003-11-30 00:00:00.000 missing
9841B082000 2003-12-31 00:00:00.000 missing
9841B082000 2004-01-31 00:00:00.000 missing
9841B082000 2004-02-29 00:00:00.000 Feb 29 2004 12:00AM
9841B082000 2004-02-29 00:00:00.000 Feb 29 2004 12:00AM
9841B082000 2004-02-29 00:00:00.000 Feb 29 2004 12:00AM
9841B082000 2004-02-29 00:00:00.000 Feb 29 2004 12:00AM
9841B082000 2004-02-29 00:00:00.000 Feb 29 2004 12:00AM
9841B082000 2004-02-29 00:00:00.000 Feb 29 2004 12:00AM

I really only want it to show me from 2004-02-29 forward in this accounts case, each account would be different



figured a way around this using some accounts information i have, thanks again
Go to Top of Page

djorre
Yak Posting Veteran

94 Posts

Posted - 2011-02-08 : 11:43:30
Note that this only will work when you assume al enddates are available in your account list. If there is a month that everybody is missing, it will not show up. In that case you will need to create the #date table elseway.

I saw you used a temp table #date so I assume you are working with stored procedures?
The easiest thing I can think of now is to delete all the records out of the result set that you do not need.

something like

create table #result(id int identity(1,1), accountnumber varchar(100), ...... , firstdatetime datetime)
insert into #result (accountnumber,....)
select * from myquery

declare @counter int, @countermax int, @lowestdatee datetime, @accountnumber varchar(100)
set @counter = 0
set @countermax = (select max(id) from #result)

while @counter <= @countermax
begin
set @accountnumber = (Select accountnumber from #results where id = @counter)
set @lowestdatetime = (Select min(date) from #results where accountnumber = @accountnumber)
update #results set firstdatetime = @lowestdatetime where id = @counter
set @counter = @counter + 1
end

delete from #results where datetime < firstdatetime

select * from #results

Note this is very amature code and way of dealing. You will need to debug it a bit. I am sure there are better ways but since no one replied I hope I helped you.
Go to Top of Page

bwperrin
Starting Member

2 Posts

Posted - 2011-02-11 : 22:18:22
Yes, there's a better way.
1. create (and keep) an integers table - useful in a host of character manipulation and other miscellaneous duties:
	select top 1000 identity(smallint) as n into integers from sysobjects a cross join sysobjects b
create unique clustered index ix_integers_n on integers(n)
2. assuming some @startdate, determine the set of all months:
	select month = dateadd(m, datediff(m, 0, @startdate) + n - 1, 0) from integers
where n - 1 <= datediff(m, @startdate, getdate())
3. determine your set of existing months:
	select distinct month = dateadd(m, datediff(m, 0, date), 0) from table where date >= @startdate
4. missing months would look like:
	select * from ({query from #2 above}) t
where month not in ({query from #3 above})
Go to Top of Page

bwperrin
Starting Member

2 Posts

Posted - 2011-02-11 : 22:25:45
whoops, for last day of month, rather than first,
change: dateadd(m, datediff(m, 0, @startdate) + n - 1, 0)
to: dateadd(m, datediff(m, 0, @startdate) + n, 0) - 1

and: dateadd(m, datediff(m, 0, date), 0)
to: dateadd(m, datediff(m, 0, date) + 1, 0) - 1
Go to Top of Page
   

- Advertisement -