0

I try to loop one sql statement multiple times to retrieve the weekly revenue of on particular store. Here is my best guess which does not work.

SELECT * 
    DECLARE @i int = 0
    WHILE @i < 52 BEGIN
        SET @i = @i + 1
        FROM dbo.revenue
        WHERE DATEPART(WW, date) = @i
        AND storenumber = '005'
    END
4

2 Answers 2

5

You actually never want to write loops in SQL.

SELECT
  SUM(earnings) weekly_earnings
FROM
  dbo.revenue
WHERE
  storenumber = '005'
  AND date >= '2015-01-01'
  AND date < '2016-01-01'
GROUP BY
  DATEPART(WW, date)

Left join that against a helper table that contains 52 rows (1 through 52) representing the weeks to fill in the blanks (weeks with no revenue).

Note that the date >= '2015-01-01' AND date < '2016-01-01' exists because:

  • you must limit the query to one year, or the week number becomes ambiguous
  • it is superior to DATEPART(YY, date) = 2015 because, being a calculation, that expression would not be able to use an index on the date column, whereas >= and < can use an index

EDIT: Instead of a temporary table you can use a recursive CTE on SQL Server:

WITH WeekNumbers (WkNum) AS (
  SELECT 1 AS WkNum
  UNION ALL
  SELECT w.WkNum + 1 FROM WeekNumbers w WHERE w.WkNum <= 52
)
SELECT
  w.WkNum,
  SUM(r.earnings) weekly_earnings
FROM
  WeekNumbers w
  LEFT JOIN dbo.revenue r ON w.WkNum = DATEPART(WW, r.date) 
WHERE
  r.storenumber = '005'
  AND r.date >= '2015-01-01'
  AND r.date < '2016-01-01'
GROUP BY
  w.WkNum
Sign up to request clarification or add additional context in comments.

5 Comments

The calendar table is an excellent point to cater for weeks with no revenue.
Thank you. I'm not used to think like this.
@greg121 Yes, the set-based approach takes some getting used to, but learning it is absolutely inevitable.
@Tomalak also great you added the recursive CTE version. But when looking at it, I see a CTE with 52 entries which is joined on the actual table. where is the recursion?
The recursion is happening in the CTE, it's self-referential. That's how it generates the 52 rows.
2

You could just group your data and use some aggregation?

Select Sum(Revenue) AS [TotalRevenuePerWeek],
       DatePart(ww, RevenueDate) as [WeekNumber]

From dbo.Revenue
Where StoreNumber = '005'
And DatePart(year, RevenueDate) = 2015
Group By DatePart(ww, RevenueDate)

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.