计算SQL中不包括当前行的平均值

计算SQL中不包括当前行的平均值,sql,sql-server,tsql,average,Sql,Sql Server,Tsql,Average,我有一个DB,其中某些记录用ID标记,我想创建一个视图,其中包含所有具有相同ID的记录的平均值,不包括当前记录。例如,如果我的数据如下所示: ROW - ID - Value 1 1 20 2 1 30 3 1 40 4 2 60 5 2 80 6 2 40 7 3 50 8 3 20 9 3 40 ROW - ID - Value AVG 1 1 20

我有一个DB,其中某些记录用ID标记,我想创建一个视图,其中包含所有具有相同ID的记录的平均值,不包括当前记录。例如,如果我的数据如下所示:

ROW - ID - Value
1     1    20
2     1    30
3     1    40
4     2    60
5     2    80
6     2    40
7     3    50
8     3    20
9     3    40
ROW - ID - Value AVG
1     1    20    35
2     1    30    30
3     1    40    25
4     2    60    60
5     2    80    50
6     2    40    70
7     3    50    30
8     3    20    55
9     3    40    35
ID | Value
1  | 4
2  | 6
3  | 5
我的视图需要计算具有相同ID的每一行的平均值,不包括它所在的行,因此我的输出如下所示:

ROW - ID - Value
1     1    20
2     1    30
3     1    40
4     2    60
5     2    80
6     2    40
7     3    50
8     3    20
9     3    40
ROW - ID - Value AVG
1     1    20    35
2     1    30    30
3     1    40    25
4     2    60    60
5     2    80    50
6     2    40    70
7     3    50    30
8     3    20    55
9     3    40    35
ID | Value
1  | 4
2  | 6
3  | 5
因此,在第3行的情况下,它提取了第1行和第2行,因为它们具有相同的ID,并且给了我它们值的平均值-25

我在这件事上四处奔走了一段时间,但似乎无法确定。任何帮助都将不胜感激

SELECT t1.gid, AVG(t2.value)
FROM table1 as t1 INNER JOIN
  table1 as t2 ON (t1.gid != t2.gid)
GROUP BY t1.gid;
基本上,根据您的条件将表连接到自身,然后根据第一个表的键对结果进行分组

无论您使用的是什么数据库系统,此解决方案都应该有效;可能有一些次要的语法细节需要更改

像这样的桌子:

ROW - ID - Value
1     1    20
2     1    30
3     1    40
4     2    60
5     2    80
6     2    40
7     3    50
8     3    20
9     3    40
ROW - ID - Value AVG
1     1    20    35
2     1    30    30
3     1    40    25
4     2    60    60
5     2    80    50
6     2    40    70
7     3    50    30
8     3    20    55
9     3    40    35
ID | Value
1  | 4
2  | 6
3  | 5
成为(加入时):


然后,分组行的聚合将产生所需的值。

如果您有窗口函数,则有一个选项

Declare @YourTable table (ROW int,ID int,Value int)
Insert Into @YourTable values
(1,     1,    20),
(2,     1,    30),
(3,     1,    40),
(4,     2,    60),
(5,     2,    80),
(6,     2,    40),
(7,     3,    50),
(8,     3,    20),
(9,     3,    40)

Select *
      ,Avg = (sum(value) over (Partition By ID)-Value)/NullIf((sum(1) over (Partition By ID)-1),0)
 From  @YourTable
另一个选项是外部应用

Select A.*
      ,B.*
 From  @YourTable A
 Outer Apply (Select Avg=avg(value) 
               From  @YourTable 
               where ID=A.ID and Row<>A.Row
              ) B
选择一个*
,B*
从@YourTable A
外部应用(选择平均值=平均值)
从@YourTable
其中ID=A.ID和RowA.Row
)B
两者都返回


此查询适用于我:

select t1.row, t1.id, t1.value, (select avg(value) from test_table as t2 where t1.id = t2.id and t1.row != t2.row) as avg from test_table as t1;
我创建的表中的数据(我假设与您的类似):

查询结果:

+-----+------+-------+---------+
| row | id   | value | avg     |
+-----+------+-------+---------+
|   1 |    1 |    20 | 35.0000 |
|   2 |    1 |    30 | 30.0000 |
|   3 |    1 |    40 | 25.0000 |
|   4 |    2 |    60 | 60.0000 |
|   5 |    2 |    80 | 50.0000 |
|   6 |    2 |    40 | 70.0000 |
|   7 |    3 |    50 | 30.0000 |
|   8 |    3 |    20 | 45.0000 |
|   9 |    3 |    40 | 35.0000 |
+-----+------+-------+---------+

你使用什么数据库?MySQL或MS SQL、Oracle、PostgreSQL…?实际上,使用t2.value,而不是t1.valueperfect!Thanks@PhilAshby在窗口选项中添加了Nullif()。这将避免被零除的情况,始终感谢您的高质量响应。