我应该如何计算多个路段的路段平均速度?

时间:2016-01-14 16:26:42

标签: sql sql-server mean

我有一张驾驶员速度和路段的表格:

driver_lpr    |   segment    |    speed
  0000001     |       A      |     30
  0000002     |       B      |     60
  0000003     |       A      |     50
  0000004     |       A      |     100
  0000005     |       B      |     60

我想要一张每段平均速度表

segment   |   average speed
   A      |         47.368
   B      |         60

如何在SQL中完成?

2 个答案:

答案 0 :(得分:20)

平均速度时,需要harmonic mean

直接AVG()方法是错误的,算术平均值会产生错误的平均速度结果。

调和均值没有预定义函数,但可以通过此查询实现:

SELECT segment,
       COUNT(*)/SUM(1e0/speed) AS avg_speed
FROM T 
GROUP BY segment

SQL Fiddle

答案 1 :(得分:3)

这有点复杂,但也会照顾0速度。我有2个类似的查询可以根据不同的场景来完成。

假设您的源表如下所示。

+-------------+----------+-------+
| driver_lpr  | segment  | speed |
+-------------+----------+-------+
|    0000001  | A        |    30 |
|    0000002  | B        |    60 |
|    0000003  | A        |    50 |
|    0000004  | A        |   100 |
|    0000005  | B        |    60 |
|    0000006  | B        |     0 |
|    0000007  | C        |     0 |
+-------------+----------+-------+

我添加了2个0速度的新行。

案例1:

  • 0段中添加B速度,将平均速度设为 40 (60*2+0*1)/(2+1)
  • C添加新细分0 速度将平均速度设为0

因此输出

+----------+-------------------+
| segment  |   average_speed   |
+----------+-------------------+
| A        | 47.36842105263158 |
| B        | 40                |
| C        | 0                 |
+----------+-------------------+

  SQLFiddle Demo CASE 1

案例2:

  • B的平均速度不会随着a的增加而改变 0
  • 但是,新细分C的平均速度为0

输出

+----------+-------------------+
| segment  |   average_speed   |
+----------+-------------------+
| A        | 47.36842105263158 |
| B        | 60                |
| C        | 0                 |
+----------+-------------------+

SQLFiddle Demo CASE 2

查询案例1:

with tbl1 as
    (SELECT segment,
    case when speed = 0 then cast(0 as float) else 
    cast(1 as float)/cast(speed as float)
    end as newspeed
    FROM T 
    ),
tbl2 as
    (
        select segment,cast(1 as float)/avg(newspeed) as avgspeed,count(*) as cnt 
        from tbl1
        where newspeed <> 0
        group by segment
    union
        select segment,0 as avgspeed,count(*) as cnt
        from tbl1
        where newspeed =0
        group by segment
    )
select segment,
    sum(avgspeed*cnt)/sum(cnt) as "average_speed" 
from tbl2
group by segment

查询Case2

with tbl1 as
    (SELECT segment,
    case when speed = 0 then cast(0 as float) else 
    cast(1 as float)/cast(speed as float)
    end as newspeed
    FROM T 
    ),
tbl2 as
    (
        select segment,cast(1 as float)/avg(newspeed) as avgspeed,count(*) as cnt 
        from tbl1
        where newspeed <> 0
        group by segment
    union
        select segment,0 as avgspeed,count(*) as cnt
        from tbl1
        where newspeed =0
        group by segment
    )
select segment,
    sum(avgspeed) as "average_speed" 
from tbl2
group by segment