好的,我有一张桌子,在一列中我有一些数据,第二列是数据的平均值。实施例
id|Data|avg
1 |20 |20
2 |4 |12
3 |18 |14
如何使用T-SQL在插入时使用数据列的运行平均值填充avg列?
编辑:对不起,伙计,这实际上是我犯的一个愚蠢的错误。我以为我有SQL 2014,但在尝试了Stephan的代码并得到一些错误后,我回去确认并意识到我使用的是SQL 2008.对于错误的信息我很抱歉。我还更新了标签答案 0 :(得分:6)
在插入时,假设id
是一个身份,而您只是放入data
:
insert into table t(id, data, avg)
select @data, @data * (1.0 / n) + avg * (n - 1.0)/n
from (select count(*) as cnt, avg(data) as avg
from t
) t;
在SQL Server 2012+中,只需将其输出即可:
select t.*, avg(data) over (order by id) as cume_avg
from table t
在SQL Server 2012之前,您可以使用相关子查询或apply
执行此操作:
select t.*,
(select avg(data)
from table t2
where t2.id <= t.id
) as cume_avg
from table t;
如果表格很大,表现可能会受到影响。但是,id, data
上的索引会有所帮助。
答案 1 :(得分:5)
IF OBJECT_ID('myTable') IS NOT NULL
DROP TABLE myTable;
CREATE TABLE myTable(ID INT, Data INT,[avg] INT);
GO
CREATE TRIGGER trg_running_avg ON myTable
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO myTable
SELECT ID,Data,AVG(Data) OVER (ORDER BY ID ROWS UNBOUNDED PRECEDING)
FROM inserted
END
INSERT INTO myTable(ID,Data)
VALUES (1,20),(2,4),(3,18)
SELECT *
FROM myTable
CREATE VIEW vw_average
AS
SELECT ID,Data,AVG(Data) OVER (ORDER BY ID ROWS UNBOUNDED PRECEDING)
FROM inserted
UPDATE myTable
SET avg = running_avg
FROM myTable A
INNER JOIN (SELECT ID,AVG(Data) OVER (ORDER BY ID ROWS UNBOUNDED PRECEDING) running_avg FROM myTable) B
ON A.ID = B.ID
WITH CTE_Update
AS
(
SELECT ID,
[avg] OldAvg,
AVG(Data) OVER (ORDER BY ID) AS NewAvg
FROM myTable
)
UPDATE CTE_Update SET OldAvg = NewAvg
答案 2 :(得分:3)
SQL Server&lt; = 2008没有聚合函数的OVER(ORDER BY ...)
子句。
CREATE TRIGGER trg_running_avg ON myTable
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
UPDATE old
SET avg = new_avg
FROM myTable old
CROSS APPLY (
SELECT AVG(Data) AS new_avg FROM myTable WHERE ID <= old.ID
) new
--Skip the full table update. Start from the lowest ID that was changed.
WHERE id >= (SELECT MIN(id) FROM (SELECT ID FROM inserted UNION ALL SELECT ID FROM deleted) t)
END
GO
如果可以,请使用视图。对于一行中的更改来说,将其他行中存储的数据无效是一种糟糕的设计。行应代表独立的事实。
答案 3 :(得分:0)
我觉得这应该通过自我加入来实现:
3
join将给出:
select t1.id, t1.data, sum(t2.data)/t1.id as avg
from table t1, table t2
where t1.id>=t2.id group by t1.id