SQL:查找响应时间中最大的百分比变化

时间:2014-01-28 17:32:15

标签: mysql sql statistics

我正在尝试计算和列出网站,以便从一个时间段到下一个时间段的响应时间总体减少最多。

我不需要使用单个查询来执行此操作,我可能会运行多个查询。

网站:

| id | url                    |
| 1  | stackoverflow.com      |
| 2  | serverfault.com        |
| 3  | stackexchange.com      |

反应:

| id | website_id | response_time | created_at |
| 1  | 1          | 93.26         | 2014-01-28 11:51:39
| 2  | 1          | 99.46         | 2014-01-28 11:52:38
| 2  | 1          | 94.51         | 2014-01-28 11:53:38
| 2  | 1          | 104.46        | 2014-01-28 11:54:38
| 2  | 1          | 85.46         | 2014-01-28 11:56:38
| 2  | 1          | 100.00        | 2014-01-28 11:57:36
| 2  | 1          | 50.00         | 2014-01-28 11:58:37
| 2  | 2          | 100.00        | 2014-01-28 11:58:38
| 2  | 2          | 80            | 2014-01-28 11:58:39

理想情况下,结果如下:

| percentage_change | website_id | 
| 52                | 1 | 
| 20                | 2 | 

我已经找到了最大的响应时间,但不知道如何进行另一个查询来计算最低响应时间,然后进行数学计算,然后对数学进行排序。

SELECT * FROM websites
LEFT JOIN (
SELECT distinct * 
       FROM responses
       ORDER BY response_time desc) responsetable
ON websites.id=responsetable.website_id group by website_id

由于

5 个答案:

答案 0 :(得分:5)

您需要等效的lag()lead()功能。在MySQL中,我使用相关子查询来执行此操作:

select website_id, max(1 - (prev_response_time / response_time)) * 100
from (select t.*,
             (select t2.response_time
              from table t2
              where t2.website_id = t.website_id and
                    t2.created_at < t.created_at
              order by t2.created_at desc
              limit 1
             ) as prev_response_time
      from table t
     ) t
group by website_id;

编辑:

如果您想要从最高到最低的变化:

select website_id, (1 - min(response_time) / max(response_time)) * 100
from table t
group by website_id;

答案 1 :(得分:2)

使用几个序列号: -

SELECT a.id, a.url, MAX(100 * (LeadingResponse.response_time - TrailingResponse.response_time) / LeadingResponse.response_time)
FROM
(
    SELECT website_id, created_at, response_time, @aCnt1 := @aCnt1 + 1 AS SeqCnt
    FROM responses
    CROSS JOIN
    (
        SELECT @aCnt1:=1
    ) Deriv1
    ORDER BY website_id, created_at
) TrailingResponse
INNER JOIN
(
    SELECT website_id, created_at, response_time, @aCnt2 := @aCnt2 + 1 AS SeqCnt
    FROM responses
    CROSS JOIN
    (
        SELECT @aCnt2:=2
    ) Deriv2
    ORDER BY website_id, created_at
) LeadingResponse
ON LeadingResponse.SeqCnt = TrailingResponse.SeqCnt
AND LeadingResponse.website_id = TrailingResponse.website_id
INNER JOIN websites a
ON LeadingResponse.website_id = a.id
GROUP BY a.id, a.url

SQL小提琴: -

http://www.sqlfiddle.com/#!2/ace08/1

编辑 - 不同的做法。只有在响应表上的id是按日期/时间顺序时才会有效。

SELECT a.id, a.url, MAX(100 * (r2.response_time - r1.response_time) / r2.response_time)
FROM responses r1
INNER JOIN responses r2
ON r1.website_id = r2.website_id
INNER JOIN
(
    SELECT r1.website_id, r1.id, MAX(r2.id) AS prev_id
    FROM responses r1
    INNER JOIN responses r2
    ON r1.website_id = r2.website_id
    AND r1.id > r2.id
    GROUP BY r1.website_id, r1.id
) ordering_query
ON r1.website_id = ordering_query.website_id
AND r1.id = ordering_query.id
AND r2.id = ordering_query.prev_id
INNER JOIN websites a
ON r1.website_id = a.id
GROUP BY a.id, a.url

您可以根据response_time字段而不是id执行类似的操作,但这需要网站的response_time是唯一的。

修改

刚刚看到你不仅想要连续的变化,而只需要从最高到最低的响应。假设最低点不必在最高点之后出现: -

SELECT id, url, MAX(100 * (max_response - min_response) / max_response)
FROM
(
    SELECT a.id, a.url, MIN(r1.response_time) AS min_response, MAX(r1.response_time) AS max_response
    FROM responses r1
    INNER JOIN websites a
    ON r1.website_id = a.id
    GROUP BY a.id, a.url
) Sub1

如果您只对较高响应时间之后的较低响应时间感兴趣: -

SELECT id, url, MAX(100 * (max_response - min_following_response) / max_response)
FROM
(
    SELECT a.id, a.url, MAX(r1.response_time) AS max_response, MIN(r2.response_time) AS min_following_response
    FROM responses r1
    INNER JOIN  responses r2
    ON r1.website_id = r2.website_id 
    AND (r1.created_at < r2.created_at
    OR (r1.created_at = r2.created_at
    AND r1.id < r2.id))
    INNER JOIN websites a
    ON r1.website_id = a.id
    GROUP BY a.id, a.url
) Sub1

(假设响应表上的id字段是唯一的并且按顺序创建)

答案 2 :(得分:1)

从你的“我已经找到最大的响应时间,但不知道如何进行另一个查询来计算最低的响应时间,然后进行数学运算,然后对数学进行排序。”我明白你想要最短的响应时间和最大的响应时间并做数学。

    drop table #test
 create table #test(
 id int, website_id int, response_time decimal, created_at datetime)
insert into #test (id , website_id , response_time , created_at) values ( 1  , 1          , 93.26, '2014-01-28 11:51:39')
insert into #test (id , website_id , response_time , created_at) values ( 2  , 1          , 99.46         , '2014-01-28 11:52:38')
insert into #test (id , website_id , response_time , created_at) values ( 2  , 1          , 94.51         , '2014-01-28 11:53:38')
insert into #test (id , website_id , response_time , created_at) values ( 2  , 1          , 104.46        , '2014-01-28 11:54:38')
insert into #test (id , website_id , response_time , created_at) values ( 2  , 1          , 85.46         , '2014-01-28 11:56:38')
insert into #test (id , website_id , response_time , created_at) values ( 2  , 1          , 100.00        , '2014-01-28 11:57:38')
insert into #test (id , website_id , response_time , created_at) values ( 2  , 1          , 50.00         , '2014-01-28 11:58:38')
insert into #test (id , website_id , response_time , created_at) values ( 2  , 2          , 100.00        , '2014-01-28 11:58:38')
insert into #test (id , website_id , response_time , created_at) values ( 2  , 2          , 80            , '2014-01-28 11:58:38')

select * from #test
select distinct  MINT.website_id,MINT.MINRT,maxT.MINRT,(MINT.MINRT/maxT.MINRT)*100--Do your calculation here---
from #test t0
inner join(select min(response_time) as MINRT,website_id from #test   group by website_id  )  MINT
 on  MINT.website_id = t0.website_id
inner join(select max(response_time) as MINRT,website_id from #test   group by website_id  )  maxT
 on  maxT.website_id = t0.website_id

答案 3 :(得分:1)

您想将最短响应时间除以每个网站的最长响应时间吗?那只是:

select 
  websites.id as website_id, 
  100 - min(response_time) / max(response_time) * 100 as percentage_change
from websites
left join responses on websites.id = responses.website_id
group by websites.id;

(我假设response_time永远不会为零。如果可以的话,你将不得不使用case语句。)

答案 4 :(得分:0)

website_id对响应时间进行分组,找到MIN(response_time)MAX(response_time),并比较MIN()MAX()是否仅过滤了可提高其效果的网站。

<?php
$rows = $db->fetchAll('
    select
      r.website_id, min(r.response_time) min_time, max(r.response_time) max_time,
      (select
         rmin.created_at
       FROM
         responses rmin
       WHERE
         rmin.response_time = min(r.response_time) AND
         rmin.website_id = r.website_id
       ORDER BY rmin.created_at
       LIMIT 1) min_created_at,
      (select
         rmax.created_at
       FROM
         responses rmax
       WHERE
         rmax.response_time = max(r.response_time) AND
         rmax.website_id = r.website_id
       ORDER BY rmax.created_at DESC
       LIMIT 1) max_created_at
    FROM
      responses r
    GROUP BY
      r.website_id');

foreach($rows as $row) {
    if($row['max_created_at'] < $row['min_created_at']) {
        echo 'Website '.$row['website_id'].
                ' improved by '.
                (100 - (($row['min_time'] / $row['max_time']) * 100)).
                "%\n";
    }
}

然而,对于大型数据集,查询可能很慢。您必须优化索引和/或查询 sqlfiddle:http://www.sqlfiddle.com/#!2/fa8f9/8