我有下表
Date Value promo item
01/01/2011 626 0 1230
01/02/2011 231 1 1230
01/03/2011 572 1 1230
01/04/2011 775 1 1230
01/05/2011 660 1 1230
01/06/2011 662 1 1230
01/07/2011 541 1 1230
01/08/2011 849 1 1230
01/09/2011 632 1 1230
01/10/2011 906 1 1230
01/11/2011 961 1 1230
01/12/2011 361 0 1230
01/01/2012 461 0 1230
01/02/2012 928 1 1230
01/03/2012 855 0 1230
01/04/2012 605 0 1230
01/05/2012 83 0 1230
01/06/2012 44 0 1230
01/07/2012 382 0 1230
01/08/2012 862 0 1230
01/09/2012 549 0 1230
01/10/2012 632 0 1230
01/11/2012 2 0 1230
01/12/2012 26 0 1230
我尝试计算最小日期和最长日期之间的平均总和(SoldAmt)/数字od天数,按照文章
回滚促销= 1的前28行(4周)无论日折扣如何,平滑期均为4周。
也就是说,如果此项目在过去4周内推广一周,则平滑时间超过5周,而不考虑促销周。
如何计算促销= 1的前4周/ 28周数据顺序?
我试试
CREATE TABLE #RollingTotalsExample
(
[Date] DATE
,[Value] INT
,promo float
,item int
);
INSERT INTO #RollingTotalsExample
SELECT '2011-01-01',626,1,1230
UNION ALL SELECT '2011-02-01',231,1,1230 UNION ALL SELECT '2011-03-01',572,1,1230
UNION ALL SELECT '2011-04-01',775,1,1230 UNION ALL SELECT '2011-05-01',660,1,1230
UNION ALL SELECT '2011-06-01',662,1,1230 UNION ALL SELECT '2011-07-01',541,1,1230
UNION ALL SELECT '2016-08-01',849,1,1230 UNION ALL SELECT '2016-09-01',632,1,1230
UNION ALL SELECT '2016-10-01',906,1,1230 UNION ALL SELECT '2016-11-01',961,1,1230
UNION ALL SELECT '2016-04-01',775,1,1230 UNION ALL SELECT '2016-05-01',660,1,1230
UNION ALL SELECT '2016-06-01',662,1,1230 UNION ALL SELECT '2016-07-01',541,1,1230
UNION ALL SELECT '2016-08-01',849,1,1230 UNION ALL SELECT '2016-09-01',632,1,1230
UNION ALL SELECT '2016-10-01',906,1,1230 UNION ALL SELECT '2016-11-01',961,1,1230
UNION ALL SELECT '2016-12-01',361,0,1230 UNION ALL SELECT '2012-01-01',461,0,1230
UNION ALL SELECT '2012-02-01',928,0,1230 UNION ALL SELECT '2012-03-01',855,0,1230
UNION ALL SELECT '2012-04-01',605,0,1230 UNION ALL SELECT '2012-05-01',83,0,1230
UNION ALL SELECT '2012-06-01',44,0,1230 UNION ALL SELECT '2012-07-01',382,0,1230
UNION ALL SELECT '2012-08-01',862,0,1230 UNION ALL SELECT '2012-09-01',549,0,1230
UNION ALL SELECT '2012-10-01',632,0,1230 UNION ALL SELECT '2012-11-01',2,0,1230
UNION ALL SELECT '2012-12-01',26,0,1230;
SELECT * FROM #RollingTotalsExample;
-- Rolling twelve month total by using INNER JOIN
SELECT a.[Date]
,Value=MAX(CASE WHEN a.[Date] = b.[Date] THEN a.Value END)
,Rolling12Months=CASE
WHEN ROW_NUMBER() OVER (ORDER BY a.[Date]) < 12
THEN NULL
ELSE SUM(b.Value)
END
FROM #RollingTotalsExample a
JOIN #RollingTotalsExample b ON b.[Date] BETWEEN DATEADD(month, -11, a.[Date]) AND a.[Date]
GROUP BY a.[Date]
ORDER BY a.[Date];
现在如何修改查询以计算最小日期和最大日期之间的平均总和(SoldAmt)/数字od天数,按照文章
回滚促销= 1的28个第一行数据顺序答案 0 :(得分:1)
因为没有陈述/显示&#34;预期结果&#34;我猜的很多。虽然我已经阅读了这个问题的文字,the duplicate,但我真的不理解这个描述。有了这些保留,我建议如下:
结果:
| item | promo_start | max_date | sum | count | avg |
|------|-------------|-------------|------|-------|-----|
| 1230 | Jan 02 2011 | Jan 12 2011 | 7150 | 11 | 650 |
| 1230 | Jan 02 2012 | Jan 12 2012 | 4968 | 11 | 451 |
由以下查询生成(使用Postgres):
select
item
, promo_start
, max(thedate) max_date
, sum(value)
, count(distinct thedate)
, sum(value) / count(distinct thedate) avg
from (
select *
from table1 t1
cross join lateral (
select min(t2.thedate) promo_start
from table1 t2
where promo = 1
and t1.item = t2.item
and t2.thedate <= t1.thedate
and t2.thedate >= t1.thedate - INTERVAL '28 DAYS'
) a
) d
where promo_start is NOT NULL
group by
item
, promo_start
;
将此视为a demo at sqlfiddle(nb:SQL Server已经/不在该网站上工作数周,因此Postgres代替使用)
注意:对于SQL Server
t1.thedate - INTERVAL '28 DAYS'
使用 dateadd(day,-28,t1.thedate) 逻辑如下:
+我用了#34; theDate&#34;作为列名仅仅是因为&#34; date&#34;在代码和描述代码中都太混乱了。我真的不能推荐使用&#34; date&#34;作为列名。
答案 1 :(得分:1)
这是另一种需要LAG()的方法,可以从SQL 2012获得,但请注意,样本数据在每个日期之前不包含“28个不同的日期”。此外,正在使用的实际数据类型是未知的(date / smalldatetime / datetime / datetime2),也不知道是否需要从日期截断时间。因此,有一些警告,这种方法为28个不同的日期创建了一系列日期范围(但是数据不提供这些日期范围,然后它们是28天过去的日期)。这是一个sqlfiddle demo
PostgreSQL 9.3架构设置: (因为SQL Server不在sqlfiddle上运行)
media-type = type "/" subtype *( OWS ";" OWS parameter )
查询1 :
CREATE TABLE Table1
(theDate timestamp, Value int, promo int, item int)
;
INSERT INTO Table1
(theDate, Value, promo, item)
VALUES
('2011-01-01 00:00:00', 626, 0, 1230),
('2011-01-02 00:00:00', 231, 1, 1230),
('2011-01-03 00:00:00', 572, 1, 1230),
('2011-01-04 00:00:00', 775, 1, 1230),
('2011-01-05 00:00:00', 660, 1, 1230),
('2011-01-06 00:00:00', 662, 1, 1230),
('2011-01-07 00:00:00', 541, 1, 1230),
('2011-01-08 00:00:00', 849, 1, 1230),
('2011-01-09 00:00:00', 632, 1, 1230),
('2011-01-10 00:00:00', 906, 1, 1230),
('2011-01-11 00:00:00', 961, 1, 1230),
('2011-01-12 00:00:00', 361, 0, 1230),
('2012-01-01 00:00:00', 461, 0, 1230),
('2012-01-02 00:00:00', 928, 1, 1230),
('2012-01-03 00:00:00', 855, 0, 1230),
('2012-01-04 00:00:00', 605, 0, 1230),
('2012-01-05 00:00:00', 83, 0, 1230),
('2012-01-06 00:00:00', 44, 0, 1230),
('2012-01-07 00:00:00', 382, 0, 1230),
('2012-01-08 00:00:00', 862, 0, 1230),
('2012-01-09 00:00:00', 549, 0, 1230),
('2012-01-10 00:00:00', 632, 0, 1230),
('2012-01-11 00:00:00', 2, 0, 1230),
('2012-01-12 00:00:00', 26, 0, 1230)
;
<强> Results 强>:
select
t1.item
, ranges.theStart
, ranges.theEnd
, sum(t1.value)
, sum(t1.value) / 28 avg
from (
select
coalesce(lag(theDay,28) over(order by theDay) , theDay - INTERVAL '28 DAYS') as theStart
, theDay as theEnd
from (
select distinct cast(thedate as date) theDay from Table1
) days
) ranges
inner join table1 t1 on theDate between ranges.theStart and ranges.theEnd
group by
t1.item
, ranges.theStart
, ranges.theEnd
注意:对于SQL Server
| item | thestart | theend | sum | avg |
|------|----------------------------|---------------------------|------|-----|
| 1230 | December, 04 2010 00:00:00 | January, 01 2011 00:00:00 | 626 | 22 |
| 1230 | December, 05 2010 00:00:00 | January, 02 2011 00:00:00 | 857 | 30 |
| 1230 | December, 06 2010 00:00:00 | January, 03 2011 00:00:00 | 1429 | 51 |
| 1230 | December, 07 2010 00:00:00 | January, 04 2011 00:00:00 | 2204 | 78 |
| 1230 | December, 08 2010 00:00:00 | January, 05 2011 00:00:00 | 2864 | 102 |
| 1230 | December, 09 2010 00:00:00 | January, 06 2011 00:00:00 | 3526 | 125 |
| 1230 | December, 10 2010 00:00:00 | January, 07 2011 00:00:00 | 4067 | 145 |
| 1230 | December, 11 2010 00:00:00 | January, 08 2011 00:00:00 | 4916 | 175 |
| 1230 | December, 12 2010 00:00:00 | January, 09 2011 00:00:00 | 5548 | 198 |
| 1230 | December, 13 2010 00:00:00 | January, 10 2011 00:00:00 | 6454 | 230 |
| 1230 | December, 14 2010 00:00:00 | January, 11 2011 00:00:00 | 7415 | 264 |
| 1230 | December, 15 2010 00:00:00 | January, 12 2011 00:00:00 | 7776 | 277 |
| 1230 | December, 04 2011 00:00:00 | January, 01 2012 00:00:00 | 461 | 16 |
| 1230 | December, 05 2011 00:00:00 | January, 02 2012 00:00:00 | 1389 | 49 |
| 1230 | December, 06 2011 00:00:00 | January, 03 2012 00:00:00 | 2244 | 80 |
| 1230 | December, 07 2011 00:00:00 | January, 04 2012 00:00:00 | 2849 | 101 |
| 1230 | December, 08 2011 00:00:00 | January, 05 2012 00:00:00 | 2932 | 104 |
| 1230 | December, 09 2011 00:00:00 | January, 06 2012 00:00:00 | 2976 | 106 |
| 1230 | December, 10 2011 00:00:00 | January, 07 2012 00:00:00 | 3358 | 119 |
| 1230 | December, 11 2011 00:00:00 | January, 08 2012 00:00:00 | 4220 | 150 |
| 1230 | December, 12 2011 00:00:00 | January, 09 2012 00:00:00 | 4769 | 170 |
| 1230 | December, 13 2011 00:00:00 | January, 10 2012 00:00:00 | 5401 | 192 |
| 1230 | December, 14 2011 00:00:00 | January, 11 2012 00:00:00 | 5403 | 192 |
| 1230 | December, 15 2011 00:00:00 | January, 12 2012 00:00:00 | 5429 | 193 |
使用 dateadd(day,-28,theDay) 答案 2 :(得分:0)
如果您正在寻找除了前12天之外的所有日子的累计金额......
with cte
as
(
select dateadd(day,12,min(date)) as mindate,max(date) as maxdate,
datediff(day,dateadd(day,12,min(date)),max(date)) as n
from #RollingTotalsExample
)
select
date,
(select sum(value) from #RollingTotalsExample t2 where t2.date<=t1.date) as rollingsum,
promo,
item,
mindate,
maxdate
from
#RollingTotalsExample t1
join
cte c
on t1.date >=c.mindate and t1.date<= c.maxdate
order by date
- 这符合您的确切输出
with cte
as
(
select dateadd(day,12,min(date)) as mindate,max(date) as maxdate,
datediff(day,dateadd(day,12,min(date)),max(date)) as n
from #RollingTotalsExample
)
select
date,
sum(value) as avgsum,
promo,
item
from
#RollingTotalsExample t1
join
cte c
on t1.date >=c.mindate and t1.date<= c.maxdate
where promo=1
group by date,promo,item
order by date
---如果您正在寻找平均值/天数
with cte
as
(
select dateadd(day,12,min(date)) as mindate,max(date) as maxdate,
datediff(day,dateadd(day,12,min(date)),max(date)) as n
from #RollingTotalsExample
)
select
date,
sum(value)/n*1.0 as avgsum,
promo,
item
from
#RollingTotalsExample t1
join
cte c
on t1.date >=c.mindate and t1.date<= c.maxdate
where promo=1
group by date,promo,item,n
order by date