Check if date is exists among the dates then add extra one day to that date - sql

i want to add the days(for example 3 days) to the given date. Before adding days we can check the holidays which are already configured in one table.
Here is my sample code. But i am unable to achieve it.
declare #HolidaysList NVARCHAR(250) = '2014-06-29,2014-07-02,2014-07-18,2014-07-30,2014-10-26'
DECLARE #RDATE DATE = '2014-06-28'
declare #addDays int = 3
declare #count int = 0
while(#count < #addDays)
BEGIN
set #RDATE = DATEADD(DAY,1,#RDATE)
--print '1 ' +cast( #RDATE as nvarchar(100))
if exists(SELECT ITEM FROM fnSplit(#HolidaysList,',') WHERE item = #RDATE)
begin
SELECT #RDATE= CONVERT(VARCHAR(10),DATEADD(DAY,1,#RDATE),101)
PRINT 'if '+ CAST( #HRDATE AS NVARCHAR(100))
end
set #count = #count+1
END
PRINT #RDATE
Here fnSplit is a function which returns a table.
In the above script i have to add 3 days to #RDate. Before adding i have to check holidays list i.e in #HolidaysList. If holiday is come then we can add extra date.
in the above script the output is: 2014-08-03 because 29th is holiday and 2nd is also holiday. so output will be 2014-08-03

You can do this without loops:
DECLARE #Holidays TABLE (Item DATE);
INSERT #Holidays
VALUES ('2014-06-29'),('2014-07-02'),('2014-07-18'),('2014-07-30'),('2014-10-26');
DECLARE #RDATE DATE = '2014-06-28',
#addDays INT = 3;
WITH CTE AS
( SELECT *,
RowNumber = ROW_NUMBER() OVER(ORDER BY d.Date)
FROM ( SELECT DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY object_id), #RDATE)
FROM sys.all_objects
) AS d (Date)
WHERE NOT EXISTS
( SELECT 1
FROM #Holidays AS h
WHERE h.Item = d.Date
)
)
SELECT Date
FROM CTE
WHERE RowNumber = #addDays;
The principal is this part:
SELECT Date = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY object_id), #RDATE)
FROM sys.all_objects
Will just generate a list of dates onwards from your starting date. You then exclude all holidays from this list using NOT EXISTS, and add a rank to all these days using ROW_NUMBER(). It is then just a case of selecting the date with the required rank.

declare #HolidaysList NVARCHAR(250) = '2014-06-29,2014-06-30,2014-07-01,2014-07-30,2014-07-18,2014-10-26'
DECLARE #RDATE DATE = '2014-06-28'
declare #addDays int = 3
declare #count int = 0
DECLARE #EXISTS int = 0
while(#count < #addDays)
BEGIN
set #RDATE = DATEADD(DAY,1,#RDATE)
if exists(SELECT ITEM FROM fnSplit(#HolidaysList,',') WHERE item = #RDATE)
set #EXISTS = #EXISTS+1
set #count = #count+1
END
if(#EXISTS is not null)
set #RDATE = DATEADD(DAY,#EXISTS,#RDATE)
print #RDATE

Related

While Loop SQL not populating complete results

Question: the iteration happens only till record 131 and gives accurate value, after that the parameter #ADE_END_DATE returns a NULL value, why would that be? Below is my code.
Additionally I noticed the column Leave_Date has NULL values and the iteration stops and returns NULL value for the parameter #ADE_END_DATE where the NULL value starts.
Thanks for your help.
BEGIN
DECLARE #HIREDATEPlus1Yr DATETIME
DECLARE #ADE_Leave_Date DATETIME
DECLARE #ADE_End_Date DATETIME
DECLARE #ADE_Start_Date DATETIME
DECLARE #DATECAL DATETIME
DECLARE #i INT
DECLARE #j INT
DECLARE #Loop_length INT
DECLARE #ID VARCHAR(18)
-- start of loop
SET #j = 1
-- Loop length will equal to the list of all ADRs
SET #Loop_Length = (SELECT COUNT([AD_ID])
FROM [DS_ADHOC_MOPs].[ADE].[List]
WHERE Status NOT IN ('MANAGER', 'TBH', 'FROZEN'))
-- Loop through each ADRs
WHILE (#j <= #Loop_length)
BEGIN
-- Loop through each ADRs
SET #i = 0
-- Find AD ID
SET #ID = (SELECT TOP 1 [AD_ID] FROM [DS_ADHOC_MOPs].[ADE].[List]
WHERE [AD_ID] NOT IN (SELECT TOP (#j-1) [AD_ID]
FROM [DS_ADHOC_MOPs].[ADE].[List]
WHERE ([AD_ID] IS NOT NULL
AND Status NOT IN ('MANAGER', 'TBH', 'FROZEN'))))
-- Find the start date of the ADR
SET #ADE_Start_Date = (SELECT TOP 1 [Hire_Date]
FROM [DS_ADHOC_MOPs].[ADE].[List]
WHERE [AD_ID] NOT IN (SELECT TOP (#j-1) [AD_ID]
FROM [DS_ADHOC_MOPs].[ADE].[List]
WHERE ([AD_ID] IS NOT NULL
AND Status NOT IN ('MANAGER', 'TBH', 'FROZEN'))))
-- Hire date plus 1 year
SET #HIREDATEPlus1Yr = DATEADD(YEAR, 1, #ADE_Start_Date)
--Adding Leave Date
SET #ADE_Leave_Date = (SELECT TOP 1 [LEAVE_DATE]
FROM [DS_ADHOC_MOPs].[ADE].[List]
WHERE [AD_ID] NOT IN (SELECT TOP (#j-1) [AD_ID]
FROM [DS_ADHOC_MOPs].[ADE].[List]
WHERE ([AD_ID] IS NOT NULL
AND Status NOT IN ('MANAGER', 'TBH', 'FROZEN'))))
-- Set a temporary variable which will be 1 year from now. Use the Date ADD formulae to start date, if they are leaver before one year then add leave date (Use IF): DONE
-- Put everything inside the while loop and add opportunity selecting to it.
IF #ADE_Leave_Date IS NULL
SET #ADE_End_Date = DATEADD(YEAR, 1, #ADE_Start_Date)
ELSE IF #HIREDATEPlus1Yr < #ADE_Leave_Date
SET #ADE_End_Date = DATEADD(YEAR, 1, #ADE_Start_Date)
ELSE
SET #ADE_End_Date = #ADE_Leave_Date
SET #DATECAL = datediff(DAY, #ADE_Start_Date, #ADE_End_Date)
SET #j = #j + 1
UPDATE #TEMPTABLEEEE
SET [#ADE_End_Date] = #ADE_End_Date
WHERE #ID = AD_ID
END
SELECT * FROM #TEMPTABLEEEE
END
I'm not sure why you are using a WHILE loop. It looks like this code could be much simplified. SQL is a set based language. Whenever possible, you should try to handle your data as a whole set instead of breaking it down into row by row evaluations.
Does this give you what you need? If the table has more than one row for each AD_ID, you will need to get the MAX() or MIN() Hire_Date/LEAVE_DATE. To improve the answer, consider providing sample data.
UPDATE t
SET [#ADE_End_Date] = ed.ADE_EndDate
FROM #TEMPTABLEEEE AS t
INNER JOIN (
SELECT AD_ID
,CASE
WHEN LEAVE_DATE IS NULL THEN DATEADD(YEAR,1,Hire_Date)
WHEN DATEADD(YEAR,1,Hire_Date) < LEAVE_DATE THEN DATEADD(YEAR,1,Hire_Date)
ELSE LEAVE_DATE
END AS ADE_EndDate
FROM DS_ADHOC_MOPs.ADE.List
WHERE Status NOT IN ('MANAGER', 'TBH', 'FROZEN')
) AS ed ON t.AD_ID = ed.AD_ID

How to calculate no. of days between two datetime column in SQL Server

There are two tables, T1 includes start date column and T2 includes end date column. Both the columns have both date and time.
T1 has all the rows unique while T2 can have multiple rows for same id and in all the row the end date column might be different (each row with different date and time).
I want to calculate the difference (no. of days) between End date and the start date while keeping in mind that we have to only pick the last date which is lying in the End date column.
;WITH MaxEndDate AS
(
SELECT
T2.PrimaryKey,
MaxEndDate = MAX(EndDate)
FROM
T2
GROUP BY
T2.PrimaryKey
)
SELECT
T1.PrimaryKey,
T1.StartDate,
M.MaxEndDate,
AmountDays = DATEDIFF(DAY, T1.StartDate, M.MaxEndDate)
FROM
T1
INNER JOIN MaxEndDate AS M ON T1.PrimaryKey = M.PrimaryKey
I would recommend creating a temporary table using T2 something like
Select Distinct ID
,MAX(ENDDATE) As [ENDDATE]
INTO #TMPTABLE1
then you include this into T1
Select A.ID
,Startdate
,B.ENDDATE
,Datediff(day,A.STARTDATE,B.ENDDATE) as DAYS
From T1 as A inner join
#TEMPTABLE1 as B on A.ID = B.ID
--------get no of days among multiple dates----------
DECLARE #i INT , #numrows INT , #days INT , #Fdate DATETIME , #Tdate DATETIME;
SET
#days = 0;
DECLARE #employee_table TABLE ( idx SMALLINT PRIMARY KEY IDENTITY(1,
1) ,
EmpId INT ,
SinceDate DATETIME ,
TillDate DATETIME );
-- populate employee table INSERT #employee_table
SELECT
EmpId ,
SinceDate ,
TillDate
FROM
T_EmpPosting_PIS
WHERE
EmpId = 18
AND OfficeTypeID = 1
ORDER BY
TransDate;
--SELECT
*
FROM
#employee_table -- enumerate the table
SET
#i = 1;
SET
#numrows = ( SELECT
COUNT(*)
FROM
#employee_table );
IF #numrows > 0 WHILE ( #i <= ( SELECT
MAX(idx)
FROM
#employee_table ) ) BEGIN
SET
#Fdate = ( SELECT
SinceDate
FROM
#employee_table
WHERE
idx = #i );
IF ( #i = #numrows ) BEGIN
SET
#Tdate = GETDATE();
END;
ELSE BEGIN
SET
#Tdate = ( SELECT
TillDate
FROM
#employee_table
WHERE
idx = #i );
END;
SET
#days = ( SELECT
DATEDIFF(DAY,
#Fdate,
#Tdate) ) #days;
SET
#i = #i 1;
END;
SELECT
#days;

SQL Server: is this a bug or do I have a misunderstanding?

Today I'm found a very sticky problem on SQL Server 2014.
Scenario: I want to pay awards to my customer (some pin code for cell phone operator)
In last cycle of loop T.Used = 0 condition is bypassed and is not working. I know in other conditions in that query (T.Cash < (#myAwards - #paid)) is there a mistake and I must to use T.Cash <= (#myAwards - #paid) instead of this but please focus on main question.
Why it's happened when I update Used flag to 1 (True) then in next loop it's selected while it doesn't have a valid condition (T.Used = 0)?
DECLARE #myAwards INT = 90000,
#paid INT = 0;
DECLARE #Temp TABLE
(
Id INT NOT NULL,
Pin VARCHAR(100) NOT NULL,
Cash INT NOT NULL,
[Weight] INT NULL,
Used BIT NOT NULL
)
INSERT INTO #Temp
SELECT
UPFI.Id, UPFI.PinCode,
PT.Cash, NULL, 0
FROM
dbo.UploadedPinFactorItem UPFI WITH (NOLOCK)
INNER JOIN
dbo.PinType PT WITH (NOLOCK) ON PT.ID = UPFI.PinTypeID
WHERE
PT.Cash <= #myAwards
UPDATE T
SET [Weight] = ISNULL((SELECT COUNT(TT.Id)
FROM #Temp TT
WHERE TT.Cash = T.Cash), 0) * T.Cash
FROM #Temp T
--For debug (first picture)
SELECT * FROM #Temp
DECLARE #i int = 1
DECLARE #count int = 0
SELECT #count = COUNT([Id]) FROM #Temp C WHERE C.Used = 0
WHILE (#i <= #count AND #paid < #myAwards)
BEGIN
DECLARE #nextId INT,
#nextCash INT,
#nextFlag BIT;
-- 'T.Used = 0' condition is by passed
SELECT TOP (1)
#nextId = T.Id, #nextCash = T.Cash, #nextFlag = T.Used
FROM
#Temp T
WHERE
T.Used = 0
AND T.Cash < (#myAwards - #paid)
ORDER BY
T.[Weight] DESC, T.Cash DESC, T.Id DESC
UPDATE #Temp
SET Used = 1
WHERE Id = #nextId
SET #i = #i + 1
SET #paid = #paid + #nextCash
--Show result in second picture
SELECT
#i AS 'i', #paid AS 'paid', #nextFlag AS 'flag', #nextId AS 'marked Id',*
FROM
#temp T
ORDER BY
T.[Weight] DESC, T.Cash DESC, T.Id DESC
END
SELECT 'final', #paid, *
FROM #temp T
ORDER BY T.[Weight] DESC, T.Cash DESC, T.Id DESC
Please let me to understand this is a bug or I have misunderstanding
First screenshot:
Second screenshot (result of loop):
Third screenshot (final result):
As per my comments:
This isn't a problem with the condition, the problem is with the implemented logic. After i = 4, there are no more rows where T.Used = 0 AND T.Cash < (#myAwards - #paid), that makes it so your reassigning variables gets zero rows, so they mantain the previous values.
You can test this behavior by doing:
DECLARE #A INT = 10;
SELECT #A = object_id
FROM sys.all_objects
WHERE name = 'an object that doesn''t exist'
SELECT #A;

SQL Right Join?

Arrrgh, I am not getting this.
I have a table of accounts from Dynamics GP that has 7 columns. I need to fill in the blank months for accounts that didn't have any activity for a given month.
I have created an in memory table #MONTHS that has lines like so:
Account, Description, Year, Month, Month Name, Netchange, PeriodBal
1110000, NULL, 2006, 1, NULL, 0, NULL
This should match up with the same information coming from Dynamics GP. A similar line from GP would look like this:
1110000, Petty Cash, 2006, 1, January, 15.00, 343.97
If we did not spend any petty cash in February, then there would be no line for that account in 2/2006, I want to make the #MONTHS table RIGHT JOIN with the DynamicsGP table so that empty months are filled in.
Here's the abbreviated SQL shortened for readability:
SELECT Z.GPACCOUNTNO,
Z.DESCRIPTION,
Z.FISCALYEAR,
Z.FISCALPERIOD,
Z.FISCALPERIODNAME,
Z.NETCHANGE,
Z.PERIODBALANCE
FROM Z
RIGHT JOIN #MONTHS M
ON Z.GPACCOUNTNO = M.GPACCOUNTNO
AND Z.FISCALPERIOD = M.FISCALPERIOD
AND Z.FISCALYEAR = M.FISCALYEAR
The SQL just runs forever. (i.e. 5 minutes before I lose my patience)
I have verified that my #MONTHS table looks like I intend. I have tried doing a "UNION ALL" with the two tables and it gives me duplicates.
If Table Z does not have a current line for a given account/year/month, I want my #MONTHS table to add that line with a Netchange balance of 0.
Thank you for your help. The full SQL is below.
/* Create in memory table to hold account numbers */
DECLARE #i int
DECLARE #c int
DECLARE #ACCT char(129)
DECLARE #numrows int
DECLARE #numyears int
DECLARE #y int
DECLARE #m int
DECLARE #ACCT_TABLE TABLE (
idx smallint Primary Key IDENTITY(1,1),
account char(129)
)
/* Populate account number table */
INSERT #ACCT_TABLE
select distinct ACTNUMST from SBM01.[dbo].[GL00105]
/* Year table reads available years in the DB */
DECLARE #YEAR_TABLE TABLE (
idx smallint Primary Key IDENTITY(1,1),
YEAR1 smallint
)
/* Populate year table */
INSERT #YEAR_TABLE
SELECT distinct YEAR1 FROM SBM01.dbo.SY40101 ORDER BY YEAR1
/* Create our table of months to UNION to the main accounts */
DECLARE #MONTHS table (
GPACCOUNTNO char(129),
DESCRIPTION char(51),
FISCALYEAR smallint ,
FISCALPERIOD smallint,
FISCALPERIODNAME char(21),
NETCHANGE numeric(19, 5),
PERIODBALANCE numeric(19, 5)
)
/* Here comes the heavy lifting.
We loop over the account numbers and add year and month values.
*/
SET #i = 1
SET #numrows = (SELECT COUNT(*) FROM #ACCT_TABLE)
IF #numrows > 0
WHILE(#i <= (SELECT MAX(idx) FROM #ACCT_TABLE))
BEGIN
/* Get the next account number */
SET #ACCT = (SELECT account FROM #ACCT_TABLE WHERE idx = #i)
SET #c = 1
SET #numyears = (SELECT COUNT(*) FROM #YEAR_TABLE)
WHILE(#c <= (SELECT MAX(idx) FROM #YEAR_TABLE))
BEGIN
SET #y = (SELECT YEAR1 FROM #YEAR_TABLE WHERE idx = #c)
SET #m = '0'
WHILE(#m < '13')
BEGIN
INSERT INTO #MONTHS (GPACCOUNTNO, DESCRIPTION, FISCALPERIOD, FISCALYEAR, FISCALPERIODNAME, NETCHANGE, PERIODBALANCE)
VALUES (#ACCT, NULL, #m, #y, NULL, '0', NULL)
SET #m = #m + 1
END
SET #c = #c + 1
END
SET #i = #i + 1
END
/* We should now have a populated Database */
SELECT Z.GPACCOUNTNO, Z.DESCRIPTION, Z.FISCALYEAR, Z.FISCALPERIOD, Z.FISCALPERIODNAME, Z.NETCHANGE, Z.PERIODBALANCE
FROM ( SELECT RTRIM(B.[ACTNUMST]) AS GPACCOUNTNO,
RTRIM(C.[ACTDESCR]) AS DESCRIPTION,
A.[YEAR1] AS FISCALYEAR,
A.[PERIODID] AS FISCALPERIOD,
E.[PERNAME] AS FISCALPERIODNAME,
ISNULL(A.[PERDBLNC], 0) AS NETCHANGE,
( SELECT ISNULL(SUM(D.[PERDBLNC]), 0)
FROM SBM01.[dbo].[GL10110] D
WHERE D.[ACTINDX] = A.[ACTINDX]
AND D.[YEAR1] = A.[YEAR1]
AND D.[PERIODID] <= A.[PERIODID]
) AS PERIODBALANCE
FROM SBM01.[dbo].[GL10110] A
INNER JOIN SBM01.[dbo].[GL00105] B ON B.[ACTINDX] = A.[ACTINDX]
INNER JOIN SBM01.[dbo].[GL00100] C ON C.[ACTINDX] = A.[ACTINDX]
INNER JOIN SBM01.[dbo].[SY40100] E ON E.[YEAR1] = A.[YEAR1]
AND E.[PERIODID] = A.[PERIODID]
AND E.[SERIES] = 0
UNION ALL
SELECT RTRIM(B.[ACTNUMST]) AS GPACCOUNTNO,
RTRIM(C.[ACTDESCR]) AS DESCRIPTION,
A.[YEAR1] AS FISCALYEAR,
A.[PERIODID] AS FISCALPERIOD,
E.[PERNAME] AS FISCALPERIODNAME,
ISNULL(A.[PERDBLNC], 0) AS NETCHANGE,
( SELECT ISNULL(SUM(D.[PERDBLNC]), 0)
FROM SBM01.[dbo].[GL10111] D
WHERE D.[ACTINDX] = A.[ACTINDX]
AND D.[YEAR1] = A.[YEAR1]
AND D.[PERIODID] <= A.[PERIODID]
) AS PERIODBALANCE
FROM SBM01.[dbo].[GL10111] A
INNER JOIN SBM01.[dbo].[GL00105] B ON B.[ACTINDX] = A.[ACTINDX]
INNER JOIN SBM01.[dbo].[GL00100] C ON C.[ACTINDX] = A.[ACTINDX]
INNER JOIN SBM01.[dbo].[SY40100] E ON E.[YEAR1] = A.[YEAR1]
AND E.[PERIODID] = A.[PERIODID]
AND E.[SERIES] = 0
) Z
RIGHT JOIN #MONTHS M
ON Z.GPACCOUNTNO = M.GPACCOUNTNO
AND Z.FISCALPERIOD = M.FISCALPERIOD
AND Z.FISCALYEAR = M.FISCALYEAR
ORDER BY Z.[GPACCOUNTNO],
M.[FISCALYEAR],
M.[FISCALPERIOD]
Why don't you use the #Months table as the starting point (since it already gives you all the months you need) and fill-in the values from Z if they are available?
SELECT
M.GPACCOUNTNO,
M.DESCRIPTION,
M.FISCALYEAR,
M.FISCALPERIOD,
M.FISCALPERIODNAME,
ISNULL(Z.NETCHANGE, 0) as NETCHANGE
ISNULL(Z.PERIODBALANCE, 0) as PERIODBALANCE
FROM #MONTHS M
LEFT JOIN Z
ON Z.GPACCOUNTNO = M.GPACCOUNTNO
AND Z.FISCALPERIOD = M.FISCALPERIOD
AND Z.FISCALYEAR = M.FISCALYEAR
You can use a SQL case statement to join when null
CREATE TABLE #TMP
(
id int,
[month] datetime
)
INSERT INTO #TMP(id,[month])values(1,GETDATE())
INSERT INTO #TMP(id,[month])values(2,null)
INSERT INTO #TMP(id,[month])values(3,GETDATE())
INSERT INTO #TMP(id,[month])values(4,GETDATE())
CREATE TABLE #TMP2
(
id int,
[month] datetime
)
INSERT INTO #TMP2(id,[month])values(1,GETDATE())
INSERT INTO #TMP2(id,[month])values(2,GETDATE())
INSERT INTO #TMP2(id,[month])values(3,GETDATE())
INSERT INTO #TMP2(id,[month])values(4,GETDATE())
select * from #TMP
select * from #TMP2
SELECT #TMP.[id], case when #TMP.[month] is null then #TMP2.[month] else #TMP.month end
from #tmp
inner join #tmp2 on #tmp.id= #tmp2.id
drop table #tmp,#tmp2

SQL Server FOR EACH Loop

I have the following SQL query:
DECLARE #MyVar datetime = '1/1/2010'
SELECT #MyVar
This naturally returns '1/1/2010'.
What I want to do is have a list of dates, say:
1/1/2010
2/1/2010
3/1/2010
4/1/2010
5/1/2010
Then i want to FOR EACH through the numbers and run the SQL Query.
Something like (pseudocode):
List = 1/1/2010,2/1/2010,3/1/2010,4/1/2010,5/1/2010
For each x in List
do
DECLARE #MyVar datetime = x
SELECT #MyVar
So this would return:-
1/1/2010
2/1/2010
3/1/2010
4/1/2010
5/1/2010
I want this to return the data as one resultset, not multiple resultsets, so I may need to use some kind of union at the end of the query, so each iteration of the loop unions onto the next.
edit
I have a large query that accepts a 'to date' parameter, I need to run it 24 times, each time with a specific to date which I need to be able to supply (these dates are going to be dynamic) I want to avoid repeating my query 24 times with union alls joining them as if I need to come back and add additional columns it would be very time consuming.
SQL is primarily a set-orientated language - it's generally a bad idea to use a loop in it.
In this case, a similar result could be achieved using a recursive CTE:
with cte as
(select 1 i union all
select i+1 i from cte where i < 5)
select dateadd(d, i-1, '2010-01-01') from cte
Here is an option with a table variable:
DECLARE #MyVar TABLE(Val DATETIME)
DECLARE #I INT, #StartDate DATETIME
SET #I = 1
SET #StartDate = '20100101'
WHILE #I <= 5
BEGIN
INSERT INTO #MyVar(Val)
VALUES(#StartDate)
SET #StartDate = DATEADD(DAY,1,#StartDate)
SET #I = #I + 1
END
SELECT *
FROM #MyVar
You can do the same with a temp table:
CREATE TABLE #MyVar(Val DATETIME)
DECLARE #I INT, #StartDate DATETIME
SET #I = 1
SET #StartDate = '20100101'
WHILE #I <= 5
BEGIN
INSERT INTO #MyVar(Val)
VALUES(#StartDate)
SET #StartDate = DATEADD(DAY,1,#StartDate)
SET #I = #I + 1
END
SELECT *
FROM #MyVar
You should tell us what is your main goal, as was said by #JohnFx, this could probably be done another (more efficient) way.
You could use a variable table, like this:
declare #num int
set #num = 1
declare #results table ( val int )
while (#num < 6)
begin
insert into #results ( val ) values ( #num )
set #num = #num + 1
end
select val from #results
This kind of depends on what you want to do with the results. If you're just after the numbers, a set-based option would be a numbers table - which comes in handy for all sorts of things.
For MSSQL 2005+, you can use a recursive CTE to generate a numbers table inline:
;WITH Numbers (N) AS (
SELECT 1 UNION ALL
SELECT 1 + N FROM Numbers WHERE N < 500
)
SELECT N FROM Numbers
OPTION (MAXRECURSION 500)
declare #counter as int
set #counter = 0
declare #date as varchar(50)
set #date = cast(1+#counter as varchar)+'/01/2013'
while(#counter < 12)
begin
select cast(1+#counter as varchar)+'/01/2013' as date
set #counter = #counter + 1
end
Off course an old question. But I have a simple solution where no need of Looping, CTE, Table variables etc.
DECLARE #MyVar datetime = '1/1/2010'
SELECT #MyVar
SELECT DATEADD (DD,NUMBER,#MyVar)
FROM master.dbo.spt_values
WHERE TYPE='P' AND NUMBER BETWEEN 0 AND 4
ORDER BY NUMBER
Note : spt_values is a Mircrosoft's undocumented table. It has numbers for every type. Its not suggestible to use as it can be removed in any new versions of sql server without prior information, since it is undocumented. But we can use it as quick workaround in some scenario's like above.
[CREATE PROCEDURE [rat].[GetYear]
AS
BEGIN
-- variable for storing start date
Declare #StartYear as int
-- Variable for the End date
Declare #EndYear as int
-- Setting the value in strat Date
select #StartYear = Value from rat.Configuration where Name = 'REPORT_START_YEAR';
-- Setting the End date
select #EndYear = Value from rat.Configuration where Name = 'REPORT_END_YEAR';
-- Creating Tem table
with [Years] as
(
--Selecting the Year
select #StartYear [Year]
--doing Union
union all
-- doing the loop in Years table
select Year+1 Year from [Years] where Year < #EndYear
)
--Selecting the Year table
selec]