0

I have a very simple query that takes two dates (start and end date, ex: 01/01/2018-01/31/2018) and then take out the week number of start and end date (ex: 1 and 5). I use while loop in order to enter all week numbers in one table (ex: 1,2,3,4,5). My while loop is creating duplicate records, like multiple records for all values. I am not sure what the issue is. Can someone suggest what I am might be doing wrong?

Code:

DECLARE @StartDate datetime = '01/01/2018'
    ,@EndDate datetime = '01/31/2018'
DECLARE @StartDateWeek INT  = DATEPART(WK,@StartDate)
    ,@EndDateWeek INT   = DATEPART(WK,@EndDate)
SELECT @StartDateWeek,@EndDateWeek

DECLARE @DateRangeWeekList TABLE(
Date DATE
,WeekNumber INT)

INSERT INTO @DateRangeWeekList
SELECT  Date = @StartDate
        ,WeekNumber = @StartDateWeek
select * from @DateRangeWeekList


WHILE (SELECT MAX(WeekNumber) FROM @DateRangeWeekList) < (SELECT     @EndDateWeek)
BEGIN
INSERT INTO @DateRangeWeekList
SELECT  Date = null
        ,WeekNumber = WeekNumber +1
FROM @DateRangeWeekList
END

select * from @DateRangeWeekList

Result:

Date        WeekNumber
2018-01-01  1
NULL        2
NULL        2
NULL        3
NULL        2
NULL        3
NULL        3
NULL        4
NULL        2 and more (total 18 records)

Expected Result

Date       WeekNumber
2018-01-01 1
NULL       2
NULL       3
NULL       4
NULL       5
4
  • What is your expected resultset here? Commented Feb 9, 2018 at 17:02
  • Posted in question Commented Feb 9, 2018 at 17:05
  • 1
    Any time you write a loop in SQL, it ought to make you feel dirty and icky. It means you're probably doing something very wrong in the first place. Commented Feb 9, 2018 at 17:21
  • A tally table would be a much better approach than a loop for this. Here is a great article on the topic. sqlservercentral.com/articles/T-SQL/62867 Commented Feb 9, 2018 at 17:32

2 Answers 2

3

A recursive CTE would be far better here than a WHILE loop:

DECLARE @StartDate datetime = '01/01/2018',
        @EndDate datetime = '01/31/2018';

WITH WeekNumbers AS(
    SELECT CONVERT(date,@StartDate) AS [Date],
           1 AS WeekNumber
    UNION ALL
    SELECT NULL,
           WeekNumber + 1
    FROM WeekNumbers
    WHERE WeekNumber <= DATEDIFF(WEEK, @StartDate, @EndDate))
SELECT *
FROM WeekNumbers;

You could also, however, consider using a Calendar table. There are lots of options out there for you.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for your answer. I am aware of CTE but my question was for duplicate records. Why dups in while loop I am using?
@Stephanie Because you're selecting from the table every time and inserting the same results again. This creates a Cartesian product.
Since we are trying to avoid looping it might be worth reading this. sqlservercentral.com/articles/T-SQL/74118 Still a good answer though. :)
I still don't understand, how I would be inserting same values when under insert statement I am selecting what is already inserted and adding a +1 to it
@Stephanie Because you select all rows in the table during each loop iteration. You start the loop with 1 row. 1st iteration adds 1 row for 2 total. 2nd iteration adds 2 rows for 4 total. And so on.
1

Perhaps you can try this format for inserting your values.

INSERT INTO @DateRangeWeekList (Date, WeekNumber)
VALUES (null, WeekNumber +1)

Comments

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.