How should I calculate the average speed by road segment for multiple segments?

前端 未结 2 530
暖寄归人
暖寄归人 2021-01-29 16:30

I have a table of driver speeds and road segments:

driver_lpr    |   segment    |    speed
  0000001     |       A      |     30
  0000002     |       B      |           


        
2条回答
  •  借酒劲吻你
    2021-01-29 17:00

    This is little bit complex, but will take care of 0 speed also. I have 2 similar queries to do it based on different scenarios.

    Assume your source table like below.

    +-------------+----------+-------+
    | 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 |
    +-------------+----------+-------+
    

    I have added 2 new rows with 0 speed.

    Case 1:

    • Addition of a 0 speed in segment B, will give average speed as 40 (60*2+0*1)/(2+1).
    • Addition of a new segment, C with 0 speed will give average speed as 0

    So output would be

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

    SQLFiddle Demo CASE 1

    Case 2:

    • There will be no change in average speed of B with addition of a 0.
    • However, a new segment C will have 0 average speed.

    Output would be

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

    SQLFiddle Demo CASE 2

    Query for Case 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
    

    Query for 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
    

提交回复
热议问题