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

时间:2017-03-31 15:07:44

标签: sql sql-server tsql average

我有一个数据库,其中某些记录用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

我的视图需要计算具有相同ID的每一行的平均值,排除它所在的行,所以我的输出看起来像这样:

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

因此,在第3行的情况下,它提取了第1行和第2行,因为它们具有相同的ID并且给我平均值--25。

我现在绕着房子走了一段时间,但似乎无法钉上它。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:4)

如果您有窗口功能,可以使用一个选项

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

返回

enter image description here

答案 1 :(得分:1)

此查询适用于我:

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;

我创建的表中的数据(我假设与你的相似):

mysql> select * from test_table;
+-----+------+-------+
| 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.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 |
+-----+------+-------+---------+

答案 2 :(得分:0)

SELECT t1.gid, AVG(t2.value)
FROM table1 as t1 INNER JOIN
  table1 as t2 ON (t1.gid != t2.gid)
GROUP BY t1.gid;

基本上,根据您的条件将表连接到自身,然后根据第一个表的键对结果进行分组。

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

这样的表:

ID | Value
1  | 4
2  | 6
3  | 5

成为(加入时):

t1.ID | t2.ID | t1.Value | t2.Value
1     | 2     | 4        | 6
1     | 3     | 4        | 5
2     | 1     | 6        | 4
2     | 3     | 6        | 5
3     | 1     | 5        | 4
3     | 2     | 5        | 6

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