0

I have the following:

select distinct
    loannumber, activedt, inactivedt
from 
    smd..TABLE_NAME
where 
    loannumber = '12345678'

I want to be able to create a column that contains a value for every month/date between the activedt and inactivedt. I have seen ideas where the dates are set as variables, but in this case, the dates are coming from the table for each record. Please help. Thanks.

2
  • 2
    Sample data and desired results will reduce assumptions Commented Jan 4, 2017 at 21:15
  • 1
    A column should never contain multiple values. What I assume you really want is a row for each day between activedt and inactivedt? A calendar table may prove helpful but if you simply want those days a tally table would be a better approach. Commented Jan 4, 2017 at 21:31

3 Answers 3

1

This will give you MONTH increments. However, if you want DAY, just change MM to DD within the CROSS APPLY

We're creating an ad-hoc tally table with master..spt_values , but any table of appropriate size will do

Declare @YourTable table (loannumber varchar(25),activedt date,inactivedt date)
Insert Into @YourTable values
('12345678','2016-01-01','2017-12-31')

Select A.LoanNumber
      ,B.Date
 From  @YourTable A
 Cross Apply (
       Select Top (DateDiff(MM,A.activedt,A.inactivedt)+1) Date=DateAdd(MM,Row_Number() Over (Order By (Select null))-1,A.activedt) 
         From master..spt_values 
       ) B

Returns

LoanNumber  Date
12345678    2016-01-01
12345678    2016-02-01
12345678    2016-03-01
12345678    2016-04-01
12345678    2016-05-01
12345678    2016-06-01
12345678    2016-07-01
12345678    2016-08-01
12345678    2016-09-01
12345678    2016-10-01
12345678    2016-11-01
12345678    2016-12-01
12345678    2017-01-01
12345678    2017-02-01
12345678    2017-03-01
12345678    2017-04-01
12345678    2017-05-01
12345678    2017-06-01
12345678    2017-07-01
12345678    2017-08-01
12345678    2017-09-01
12345678    2017-10-01
12345678    2017-11-01
12345678    2017-12-01
Sign up to request clarification or add additional context in comments.

Comments

0

I suggest using Date Tables, in this article, there is an extensive explanation, the idea is that you can use for this kind of scenario.

https://www.mssqltips.com/sqlservertip/4054/creating-a-date-dimension-or-calendar-table-in-sql-server/

With this table, you can do join between tables and use the date column.

1 Comment

Thanks. But that situation is too complex for me. I would rather learn how to just make the query stop creating dates past the current date if the InactiveDt is NULL, or past the InactiveDt for each row if the InactiveDt has a value.
0

You won't beat the performance of a physical date table, but if you have less than about 2000 days in between the inactive and active dates and just need basic queries ad-hoc against it, then consider CROSS APPLY against the spt_values table.

Since I wasn't sure if if active and inactive dates where always on or before (some cases with active > inactive, and others with inactive <= active), this should work for either case:

select distinct
    loannumber, activedt, inactivedt, dtvalue
from 
    smd..TABLE_NAME
    CROSS APPLY (
        SELECT DATEADD(DD, N.number, activedt) FROM spt_values N
            WHERE N.number BETWEEN 0 AND DATEDIFF(DD, activedt, inactivedt) AND activedt <= inactivedt
        UNION ALL SELECT DATEADD(DD, N.number, inactivedt) FROM spt_values N
            WHERE N.number BETWEEN 0 AND DATEDIFF(DD, inactivedt, activedt) AND activedt > inactivedt
    ) N (dtvalue)
where 
    loannumber = '12345678'

This produced the results below for a single record loan number from 1/3 to 1/5:

loannumber activedt   inactivedt dtvalue
---------- ---------- ---------- ----------
12345678   2017-01-03 2017-01-05 2017-01-03
12345678   2017-01-03 2017-01-05 2017-01-04
12345678   2017-01-03 2017-01-05 2017-01-05

If you need to get beyond 2000, there are additional techniques to UNION ALL to generate appropriate row counts quickly.

3 Comments

Hi. I now have the following:g
How can I get the MO column to not create MO past the current date? Declare YT table (loan varchar(25),activedt date,inactivedt date) Insert Into YT select distinct loan, activedt, inactivedt from tblONE A IF OBJECT_ID(N'tempdb..#RR') is not null Drop Table #RR select loan, activedt, inactivedt, B.MO from tableONE A cross apply ( Select MO=DateAdd(MM,Row_Number() Over (Order By (Select null))-1,A.activedt) From master..spt_values ) B order by loan desc
You could add onto your last WHERE clause. In example from answer, it would be something like AND dtvalue <= GETDATE()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.