我有这个查询,按天计算测量的平均值 现在我希望在接下来的5天内从每一行获得平均值
哦......我正在使用Sql Server
这是我的
SELECT Cast(Cast (Datepart(year, Dateadd(minute, (a.quarternumber * 15),
'2000-01-01'))
AS
VARCHAR(4))
+ '-'
+ Cast (Datepart(month, Dateadd(minute, (a.quarternumber * 15),
'2000-01-01'))
AS VARCHAR(4))
+ '-'
+ Cast (Datepart(day, Dateadd(minute, (a.quarternumber * 15),
'2000-01-01')
)AS
VARCHAR(4))
+ ' ' AS DATETIME) AS [TimeStamp],
--AVG(a.value) over(order by a.value) as exper,
Round(Avg(a.value), 2) AS Value
FROM measurements.archive a
INNER JOIN measurements.points p
ON a.pointid = p.id
INNER JOIN fifthcore..cm_lod_devices ld
ON ld.uuid = p.logicaldeviceuuid
WHERE ld.id IN (SELECT value
FROM @LodDeviceIds)
AND p.name = @Name
AND a.quarternumber BETWEEN @ChartBeginNumber AND @ChartEndNumber
GROUP BY Datepart(year, Dateadd(minute, ( a.quarternumber * 15 ), '2000-01-01')
),
Datepart(month, Dateadd(minute, ( a.quarternumber * 15 ), '2000-01-01'
)),
Datepart(day, Dateadd(minute, ( a.quarternumber * 15 ), '2000-01-01'))
ORDER BY Datepart(day, Dateadd(minute, ( a.quarternumber * 15 ), '2000-01-01'))
我正在研究这样的事情,但却无法让它发挥作用
AVG(y) OVER(ORDER BY x
3 ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)
Table :extra column that would avg the result of next five days
2014-07-01 00:00:00.000 16.780000 --> 15.8
2014-07-02 00:00:00.000 15.940000 --> 16
2014-07-03 00:00:00.000 16.790000
2014-07-04 00:00:00.000 16.790000
2014-07-05 00:00:00.000 16.040000
2014-07-06 00:00:00.000 16.500000
2014-07-07 00:00:00.000 16.790000
2014-07-08 00:00:00.000 16.790000
2014-07-09 00:00:00.000 16.790000
答案 0 :(得分:2)
我认为您的问题是您正在使用AVG()
错误地使用OVER
子句。
您正在使用GROUP BY
- 因此同一查询中的AVG()
将应用于该组,而不是整个数据集,因此您无法先使用SQL SERVER 2012特定的窗口版本做子查询或CTE。
以下是我认为你可以让它发挥作用的方式,但请注意 - 此时我还没有真正测试过它。
WITH cte AS (
SELECT Cast(Cast (Datepart(year, Dateadd(minute, (a.quarternumber * 15),
'2000-01-01'))
AS
VARCHAR(4))
+ '-'
+ Cast (Datepart(month, Dateadd(minute, (a.quarternumber * 15),
'2000-01-01'))
AS VARCHAR(4))
+ '-'
+ Cast (Datepart(day, Dateadd(minute, (a.quarternumber * 15),
'2000-01-01')
)AS
VARCHAR(4))
+ ' ' AS DATETIME) AS [TimeStamp],
Round(Avg(a.value), 2) AS Value
SUM (a.value) AS ValueSum, -- New item - required for calculating windowed average from group
COUNT(a.value) AS ValueCount -- New item - required for calculating windowed average from group
FROM measurements.archive a
INNER JOIN measurements.points p
ON a.pointid = p.id
INNER JOIN fifthcore..cm_lod_devices ld
ON ld.uuid = p.logicaldeviceuuid
WHERE ld.id IN (SELECT value
FROM @LodDeviceIds)
AND p.name = @Name
AND a.quarternumber BETWEEN @ChartBeginNumber AND @ChartEndNumber
GROUP BY Datepart(year, Dateadd(minute, ( a.quarternumber * 15 ), '2000-01-01')
),
Datepart(month, Dateadd(minute, ( a.quarternumber * 15 ), '2000-01-01'
)),
Datepart(day, Dateadd(minute, ( a.quarternumber * 15 ), '2000-01-01'))
ORDER BY Datepart(day, Dateadd(minute, ( a.quarternumber * 15 ), '2000-01-01'))
)
SELECT
[TimeStamp],
Value,
SUM(ValueSum) OVER (
ORDER BY [TimeStamp] ROWS BETWEEN CURRENT ROW AND 5 FOLLOWING
) /
SUM(ValueCount) OVER (
ORDER BY [TimeStamp] ROWS BETWEEN CURRENT ROW AND 5 FOLLOWING
) AS ValueOverNext5
-- Average = SUM(x) / COUNT(x) = SUM(SUM(group)) / SUM(COUNT(group))
FROM cte
如您所见,我将您的查询放在公用表表达式中,并为SUM和COUNT添加了2个新列。然后我将窗口化的AVG OVER应用于这些项目(通过执行SUM(总计)OVER(...)/ SUM(计数)OVER(...) - 来自CTE的已经平均值的直接AVG将是不正确的)
希望这有意义并且有效!
答案 1 :(得分:1)
如果您是SQL Server 2008,那就是这样 第一部分只是制作测试数据:
DECLARE @MyTable TABLE
(
MyDate DATETIME,
Value DECIMAL(19,6)
)
INSERT INTO @MyTable
VALUES
('2014-07-01 00:00:00.000',16.780000),
('2014-07-02 00:00:00.000',15.940000),
('2014-07-03 00:00:00.000',16.790000),
('2014-07-04 00:00:00.000',16.790000),
('2014-07-05 00:00:00.000',16.040000),
('2014-07-06 00:00:00.000',16.500000),
('2014-07-07 00:00:00.000',16.790000),
('2014-07-08 00:00:00.000',16.790000),
('2014-07-09 00:00:00.000',16.790000);
现在我创建一个CTE订单我的数据并给它一个rownumber。
WITH SortedData AS
(
SELECT *,
ROW_NUMBER() OVER (ORDER BY MyDate) RN
FROM @MyTable
)
现在使用我的CTE,我得到接下来的4行avg with。
SELECT
CAST(t1.MyDate AS DATE) AS MyDate,
t1.Value,
t1.RN,
d.FCNT,
d.FSUM,
d.FAVG
FROM SortedData T1
OUTER APPLY
(
SELECT
SUM(T2.VALUE) FSUM,
COUNT(1) FCNT,
AVG(T2.Value) FAVG
FROM SortedData T2
WHERE T2.RN >= T1.RN
AND T2.RN <= T1.RN + 4
) d
ORDER BY T1.RN
这是输出:
MyDate Value RN FCNT FSUM FAVG
2014-07-01 16.780000 1 5 82.340000 16.468000
2014-07-02 15.940000 2 5 82.060000 16.412000
2014-07-03 16.790000 3 5 82.910000 16.582000
2014-07-04 16.790000 4 5 82.910000 16.582000
2014-07-05 16.040000 5 5 82.910000 16.582000
2014-07-06 16.500000 6 4 66.870000 16.717500
2014-07-07 16.790000 7 3 50.370000 16.790000
2014-07-08 16.790000 8 2 33.580000 16.790000
2014-07-09 16.790000 9 1 16.790000 16.790000
对于SQL Server 2012,它可以像这样简单: 让我们更改测试数据并为每个日期添加更多行:
DECLARE @MyTable TABLE
(
MyDate DATETIME,
Value DECIMAL(19,6)
)
INSERT INTO @MyTable
VALUES
('2014-07-01 00:00:00.000',1.0),
('2014-07-01 00:00:00.000',2.0),
('2014-07-01 00:00:00.000',3.0),
('2014-07-01 00:00:00.000',4.0),
('2014-07-02 00:00:00.000',7.0),
('2014-07-02 00:00:00.000',7.0),
('2014-07-02 00:00:00.000',7.0),
('2014-07-03 00:00:00.000',8.0),
('2014-07-04 00:00:00.000',9.0),
('2014-07-05 00:00:00.000',10.0),
('2014-07-06 00:00:00.000',11.0),
('2014-07-07 00:00:00.000',20.0),
('2014-07-08 00:00:00.000',25.0),
('2014-07-09 00:00:00.000',50.0);
现在让我们的CTE组和AVG成为数据:
WITH SortedData AS
(
SELECT
MyDate,
AVG(VALUE) DayAvg,
ROW_NUMBER() OVER (ORDER BY MyDate) RN,
AVG(AVG(VALUE)) OVER (ORDER BY MyDate ROWS between current row and 4 following) FDAVG
FROM @MyTable
GROUP BY MyDate
)
SELECT CAST(sd.MyDate AS DATE) AS MyDate,
sd.DayAvg,
sd.RN,
sd.FDAVG
FROM SortedData sd
这是输出:
MyDate DayAvg RN FDAVG
2014-07-01 2.500000 1 7.300000
2014-07-02 7.000000 2 9.000000
2014-07-03 8.000000 3 11.600000
2014-07-04 9.000000 4 15.000000
2014-07-05 10.000000 5 23.200000
2014-07-06 11.000000 6 26.500000
2014-07-07 20.000000 7 31.666666
2014-07-08 25.000000 8 37.500000
2014-07-09 50.000000 9 50.000000