2015-11-02 6 views
0

Я пытаюсь зациклировать один оператор sql несколько раз, чтобы получить еженедельный доход в определенном магазине. Вот мое лучшее предположение, которое не работает.Как спрятать инструкцию SQL несколько раз

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 
+0

Это не будет работать, то, что является вашей актуальной проблемой? Похож на http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem – HoneyBadger

+0

Не используйте петли, но устанавливайте базовые подходы http://sqlperformance.com/2013/01/t-sql -queries/generate-a-set-1 –

+0

Не можете ли вы просто сгруппировать по DATEPART (WW, дата), суммировать и спросить о соответствующем магазине – ehh

ответ

5

Вы на самом деле никогда не хотите писать циклы в 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) 

Выравнивание по левому краю, что против хелперов таблицы, которая содержит 52 строк (с 1 по 52), представляющие недели, чтобы заполнить пробелы (недели без каких-либо доходов).

Обратите внимание, что date >= '2015-01-01' AND date < '2016-01-01' существует потому, что:

  • вы должны ограничить запрос на один год, или номер недели становится неоднозначным
  • она превосходит DATEPART(YY, date) = 2015, потому что, будучи расчетом, что выражение не будет иметь возможность использовать индекс по date колонке, в то время как >= и < может использовать индекс

EDIT: Вместо временной таблицы вы можете использовать recursive CTE на 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 
+1

Календарный стол - отличная точка, чтобы обслуживать недели без прибыли. – codingbadger

+0

Спасибо. Я не привык думать так. – greg121

+2

@ greg121 Да, подход, основанный на наборах, немного привыкает, но обучение абсолютно неизбежно. – Tomalak

2

Вы можете просто сгруппировать свои данные и использовать некоторую агрегацию?

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) 
Смежные вопросы