Как суммировать общую сумму за последние 12 месяцев, используя параметры - PullRequest
2 голосов
/ 02 августа 2011

Я хочу суммировать последние 12 месяцев значения из SQL-запроса.
Проблема в том, чтобы подвести итоги за последние 12 месяцев, а не за целый год.
Поэтому, когда я выбираю март 2000 в качестве параметра по умолчанию,
Я хочу, чтобы запрос суммировался: с марта 1999 г. по март 2000 г.

Вот что я получил до сих пор:

SELECT Name, SUM(sales) as totalsales, year_month
FROM Total_Sales
WHERE 
(year_month = @year_month)
GROUP BY Name, year_month

Спасибо за любую помощь!

- EDIT -

SELECT Name, SUM(sales) as totalsales, year_month
FROM Total_Sales
WHERE 
(year_month >= @From) AND 
(year_month <= @To)
GROUP BY Name, year_month

Добавил это после предложений от "Стива Моргана"
Можем ли мы как-то добавить среднее значение за последние 12 месяцев, не выбирая 12 месяцев в параметрах. Разрешение параметру @From выбрать начальное значение. Что-то вроде: AVG (от -12 месяцев) ??

Еще раз спасибо за помощь!

- РЕДАКТИРОВАТЬ 2 -

Функция ROW_NUMBER () очень удобна для решения этой проблемы. Мой запрос теперь выглядит так:

SELECT  Name, SUM(sales)
FROM    
(               
SELECT  rn = ROW_NUMBER() OVER (PARTITION BY Name ORDER BY year, year_month)
, Name
, sales = SUM(sales)
FROM     Total_Sales ts
WHERE
(year_month>= @From) AND 
(year_month<= @To)
GROUP BY
Name
, year
, year_month
    ) ts 
WHERE
rn <= 12    

GROUP BY
Name  

Ответы [ 5 ]

3 голосов
/ 02 августа 2011

Этот код длиннее, чем Стив Морганс, но предназначен для того, чтобы оптимизатор мог использовать любой существующий индекс в полях year и year_month. Это актуально, только если у вас относительно большая таблица, так как она предназначена для эффективного определения того, какие записи можно пропустить.

(Предполагается также использование MS SQL Server, но логика применима к другим СУБД.)

DECLARE
  @DateParam AS DATETIME
SELECT
  @DateParam  = '2011 June 01'

;WITH MyTable (Name, Year, Year_Month, Sales) AS
(
             SELECT 'Rod', 2010, 1, 10
   UNION ALL SELECT 'Rod', 2010, 2, 10
   UNION ALL SELECT 'Rod', 2010, 3, 10
   UNION ALL SELECT 'Rod', 2010, 4, 10 UNION ALL SELECT 'Jane', 2010, 4, 10
   UNION ALL SELECT 'Rod', 2010, 5, 10 UNION ALL SELECT 'Jane', 2010, 5, 10
   UNION ALL SELECT 'Rod', 2010, 6, 10 UNION ALL SELECT 'Jane', 2010, 6, 10
------------------------------------------------------------------------------
   UNION ALL SELECT 'Rod', 2010, 7, 10 UNION ALL SELECT 'Jane', 2010, 7, 10
   UNION ALL SELECT 'Rod', 2010, 8, 10 UNION ALL SELECT 'Jane', 2010, 8, 10
   UNION ALL SELECT 'Rod', 2010, 9, 10 UNION ALL SELECT 'Jane', 2010, 9, 10
   UNION ALL SELECT 'Rod', 2010,10, 10 UNION ALL SELECT 'Jane', 2010,10, 10
                                       UNION ALL SELECT 'Jane', 2010,11, 10
                                       UNION ALL SELECT 'Jane', 2010,12, 10
                                       UNION ALL SELECT 'Jane', 2011, 1, 10
                                       UNION ALL SELECT 'Jane', 2011, 2, 10
   UNION ALL SELECT 'Rod', 2011, 3, 10 UNION ALL SELECT 'Jane', 2011, 3, 10
   UNION ALL SELECT 'Rod', 2011, 4, 10 UNION ALL SELECT 'Jane', 2011, 4, 10
   UNION ALL SELECT 'Rod', 2011, 5, 10
   UNION ALL SELECT 'Rod', 2011, 6, 10
------------------------------------------------------------------------------
   UNION ALL SELECT 'Rod', 2011, 7, 10
)

SELECT
  Name,
  Year,
  Year_Month,
  SUM(sales) AS Total_Sales
FROM
  MyTable
WHERE
   (Year = DATEPART(YEAR, @DateParam)     AND Year_Month <= DATEPART(MONTH, @DateParam))
OR (Year = DATEPART(YEAR, @DateParam) - 1 AND Year_Month >  DATEPART(MONTH, @DateParam))
GROUP BY
  Name,
  Year,
  Year_Month

Примечания:
1. Это даст результаты за 12 месяцев до июня 2011 года включительно
2. Данные до июля 2010 года не будут включены
3. Пробел в данных Рода не приведет к нарушению Note 3
4. Отсутствие данных Джейн в мае 2011 года и июне 2011 года не приведет к нарушению Note 3
5. Формулировка предложения WHERE позволит использовать ИНДЕКСЫ

2 голосов
/ 02 августа 2011

Я не могу сказать из вашего примера, как хранится year_month, из-за чего трудно решить, поддается ли он такому запросу.

В таких случаях я использую то, что я называю относительным месяцем., который я вычисляю как

(year - 2000) * 12 + (month -1)

Итак, январь 2000 г. - относительный месяц 0, февраль 2010 г. - относительный месяц 121 и т. д.

Это легко конвертируется в год и месяц, используяСкалярные функции SQL Server и простой запрос с использованием>, <и т. Д. </p>

Редактировать:

Только что видел ваши комментарии о том, что такое year_month, а также о том, что у вас есть год.Скалярная функция для вычисления относительного значения месяца из ваших столбцов year иmonth будет работать на вас.

Тогда вы можете сделать:

where
    dbo.GetRelativeMonth(year, year_month) >= @startRelativeMonth
    and dbo.GetRelativeMonth(year, year_month) < @endRelativeMonth

Хотя более эффективно добавить столбецlative_month квашей таблицы и вычислите значение, когда вы пишете запись.

Редактировать 2:

Вы спросили, как работает GetRelativeMonth, поэтому вот оно:

CREATE FUNCTION [dbo].[GetRelativeMonth] 
(
@Year int,
@Month int
)
RETURNS int
AS
BEGIN
DECLARE @Result int
SELECT @Result = (@Year - 2000) * 12 + (@Month - 1)
RETURN @Result
END
1 голос
/ 02 августа 2011

Если вы используете SQL Server, вы можете использовать функцию ROW_NUMBER , чтобы составить подмножество ваших данных, из которого вы можете выбрать конечный результат.

Оператор SQL

SELECT  Name
        , SUM(sales)
FROM    (               
            SELECT  rn = ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Year, Year_Month)
                    , Name
                    , sales = SUM(sales)
            FROM    @Total_Sales ts
            WHERE   (YEAR(@Param) <= ts.Year AND MONTH(@Param) <= ts.Year_Month)
                    OR (YEAR(@Param) < ts.Year)
            GROUP BY
                    Name
                    , Year
                    , Year_Month
        ) ts 
WHERE   rn <= 12        
GROUP BY
        Name                                

Данные испытаний

DECLARE @Param DATE = '05-01-2011'
DECLARE @Total_Sales TABLE (
    Name VARCHAR(32)
    , Sales INTEGER
    , Year_Month INTEGER
    , Year INTEGER
)

INSERT INTO @Total_Sales VALUES 
    ('Malcolm X', 1, 1, 2011)
    , ('Malcolm X', 1, 2, 2011)
    , ('Malcolm X', 1, 3, 2011)
    , ('Malcolm X', 1, 4, 2011)
    , ('Malcolm X', 1, 5, 2011)
    , ('Malcolm X', 1, 6, 2011)
    , ('Malcolm X', 1, 7, 2011)
    , ('Malcolm X', 1, 8, 2011)
    , ('Malcolm X', 1, 9, 2011)
    , ('Malcolm X', 1, 10, 2011)
    , ('Malcolm X', 1, 11, 2011)
    , ('Malcolm X', 1, 12, 2011)
    , ('Malcolm X', 1, 1, 2012)
    , ('Ben Hur', 1, 2, 2012)
0 голосов
/ 02 августа 2011

ВЫБРАТЬ Имя, СУММА (продажи) в виде итоговых продаж, год_месяца ОТ Всего_Продаж, ГДЕ year_month = DATEADD (MONTH, -12, '31 -March-2000 ') GROUP BY Name, year_month

Попробуйте что-то подобное1003 *

0 голосов
/ 02 августа 2011

Возможно, вы могли бы использовать функцию МЕЖДУ?где ваша дата между minValue и maxvalue

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...