Я использую SQL Server 2014. У меня есть такая таблица
create table revenue (id varchar(2), trasdate date, revenue int);
insert into revenue(id, trasdate, revenue)
values ('aa', '2018/09/01', 1234.5),
('aa' , '2018/08/04', 450),
('aa', '2018/07/03',500),
('aa', '2018/06/04',600),
('ab', '2018/09/01', 1234.5),
('ab' , '2018/08/04', 450),
('ab', '2018/07/03',500),
('ab', '2018/06/04',600),
('ab', '2018/05/03', 200),
('ab', '2018/04/02', 150),
('ab', '2018/03/01', 350),
('ab', '2018/02/05', 700),
('aa', '2018/01/07', 400)
;
Я готовлю запрос SQL для создания отчета SSRS.Я хочу рассчитать среднее значение за последние 3 месяца для текущего и каждого прошедшего 3-го месяца с результатом, как показано ниже.Как мы в сентябре месяце прямо сейчас.Результат должен показать что-то вроде этого:
**id Period Revenue_3Mon**
aa March-May 233
aa June-Aug 516
ab March-May 233
ab June-Aug 516
Хотя я могу разобраться с колонкой Period.В основном я фокусировался на получении дохода_3Мон.Поэтому я сначала попытался с приведенным ниже запросом после некоторого поиска.Но этот запрос выдает ошибку как неверный синтаксис рядом с «строками», и если я удаляю строки из запроса, он выдает ошибку как неправильный синтаксис рядом с ключевым словом «между».И неправильный синтаксис рядом с i.
select i.id,i.mon,
avg([i.mon_revenue]) over (partition by i.id, i.mon order by [i.id],
[i.mon] rows between 3 preceding and 1 preceding row) as revenue_3mon --
-- using 3 preceding and 1 preceding row you exclude the current row
from (select a.id, month(a.trasdate) as mon,
sum(a.revenue) as mon_revenue
from revenue a
group by a.id, month(a.trasdate)) i
group by i.id, i.mon
order by i.id,i.mon;
После нескольких усилий я отказался от этого запроса и нашел новое решение, которое было немного близко к моим ожиданиям (после множества проб и ошибок).
Declare @count as int;
declare @max as int;
set @count = 4
declare @temp as table (id varchar(2), monthoftrasdate int, revenue int,
[3monavg] int);
SET @MAX = (SELECT distinct MAX(a.ROWNUM) FROM (SELECT id, month(trasdate)
as mon, SUM(revenue) TotalRevenue,
-- sum(revenue) as mon_revenue,
ROW_NUMBER() OVER(PARTITION BY ID ORDER BY MONTH(TRASDATE)) AS ROWNUM
FROM revenue
GROUP BY ID, MONTH(TRASDATE)
) A GROUP BY A.ID);
while (@count <= @max )
begin
WITH CTE AS (
SELECT id, month(trasdate) as mon, SUM(revenue) TotalRevenue,
-- sum(revenue) as mon_revenue,
ROW_NUMBER() OVER(PARTITION BY ID ORDER BY MONTH(TRASDATE)) AS
ROWNUM
FROM revenue
GROUP BY ID, MONTH(TRASDATE)
)
insert into @temp
SELECT A.ID,A.MON, a.TotalRevenue
,( SELECT avg(b.TotalRevenue) as avgrev
FROM CTE B
WHERE B.ROWNUM BETWEEN A.ROWNUM-3 AND A.ROWNUM-1
AND A.ID = B.ID --AND A.mon = B.mon
--and b.ROWNUM < a.ROWNUM
and (a.mon > 3 and a.ROWNUM > 3)
GROUP BY B.id
) AS REVENUE_3MON
FROM CTE A
set @count = @count + 1
end
select distinct a.* from @temp a
Причина, по которой мне пришлось использовать «разные», заключается в том, что в запросе были показаны повторяющиеся записи для каждого идентификатора и каждого месяца.Пока результат показывает как ниже
id MonthofTrasdate Revenue 3MonAvg
aa 1 400 NULL
aa 2 700 NULL
aa 3 350 NULL
aa 4 150 483
aa 5 200 400
aa 6 600 233
aa 7 500 316
aa 8 450 433
aa 9 1234 516
ab 1 400 NULL
ab 2 700 NULL
ab 3 350 NULL
ab 4 150 483
ab 5 200 400
ab 6 600 233
ab 7 500 316
ab 8 450 433
ab 9 1234 516
Это вытягивает среднее значение за последние 3 месяца для каждого месяца.Но я буду просто манипулировать остальными на SSRS так, как я хочу.
Поскольку в настоящее время в моей таблице нет данных за предыдущий год.Это работает для меня, показывая соответствующий результат для следующих нескольких месяцев на данный момент.Но меня беспокоит то, что когда я должен показать своего босса на следующий год, январь, февраль и март, он должен быть в состоянии справиться и с этими месяцами, такими как октябрь-декабрь (предыдущий год), ноябрь-январь и декабрь-февраль.я изо всех сил пытаюсь найти правильный способ поместить это в мой запрос.
Не могли бы вы помочь мне с этим вопросом?А также дайте мне знать, что не так с моим прежним запросом.