我正在自己开发一个小项目,它是一个网站监控工具。 我有一个代理正在运行读取网页,它对网站状态代码、内容检查和响应时间使用react。
表格看起来像这样。
CREATE TABLE `data` (
`id` int(11) NOT NULL,
`check_id` int(11) NOT NULL,
`content_string_used` varchar(20) NOT NULL,
`content_check` enum('good','bad') NOT NULL,
`http_code` int(11) NOT NULL,
`total_time` varchar(5) NOT NULL,
`namelookup_time` varchar(5) NOT NULL,
`connect_time` varchar(5) NOT NULL,
`pretransfer_time` varchar(5) NOT NULL,
`starttransfer_time` varchar(5) NOT NULL,
`url` varchar(50) NOT NULL,
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
我想做的是选择特定检查的所有记录,例如
SELECT * FROM `data` WHERE `check_id` = 173;
现在事情变得棘手了,我会尽力解释清楚。 行本身有一些重要的列。它是 content_check 和 http_code。
我想要做的是以这两行作为分隔符将所有行分组,然后选择从第一个好行到最后一个好行的开始时间。
示例...
SELECT id, check_id, content_check, http_code, time from data WHERE `check_id` = 173;
结果
(15, 173, 'bad', 0, '2018-03-11 15:43:11'),
(23, 173,'bad', 0, '2018-03-11 15:44:11'),
(35, 173,'good', 0, '2018-03-11 15:45:11'),
(49, 173,'good', 0, '2018-03-11 15:46:11'),
(67, 173,'bad', 0, '2018-03-11 15:47:11'),
(85, 173,'bad', 0, '2018-03-11 15:48:11'),
(105, 173,'bad', 0, '2018-03-11 15:49:11'),
(125, 173,'good', 0, '2018-03-11 15:50:11'),
(145, 173,'bad', 0, '2018-03-11 15:51:11'),
(165, 173,'bad', 0, '2018-03-11 15:52:11');
我喜欢这样的查询,它返回类似的内容,基本上总结了好/坏,并以时间间隔作为某种分隔符。
(15, 'bad', 0, '2018-03-11 15:43:11', '2018-03-11 15:44:11'),
(35, 'good', 0, '2018-03-11 15:45:11', '2018-03-11 15:46:11'),
(67, 'bad', 0, '2018-03-11 15:47:11', 2018-03-11 15:49:11),
(125, 'good', 0, '2018-03-11 15:50:11', '2018-03-11 15:50:11'),
(145, 'bad', 0, '2018-03-11 15:51:11','2018-03-11 15:52:11'),
请帮助或指出我正确的方向。
最佳答案
解决此类问题的一个技巧是使用一对变量来跟踪最新记录的 check_id
和 http_code
,再加上第三个变量来跟踪表示一个组编号,其值仅在 check_id
或 http_code
与前面的记录不同的记录上递增。例如,给出以下设置:
CREATE TABLE `data` (
`id` int(11) NOT NULL,
`check_id` int(11) NOT NULL,
`content_check` enum('good','bad') NOT NULL,
`http_code` int(11) NOT NULL,
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
insert into `data`
(`id`, `check_id`, `content_check`, `http_code`, `time`)
values
(15, 173, 'bad', 0, '2018-03-11 15:43:11'),
(23, 173, 'bad', 0, '2018-03-11 15:44:11'),
(35, 173, 'good', 0, '2018-03-11 15:45:11'),
(49, 173, 'good', 0, '2018-03-11 15:46:11'),
(67, 173, 'bad', 0, '2018-03-11 15:47:11'),
(85, 173, 'bad', 0, '2018-03-11 15:48:11'),
(105, 173, 'bad', 0, '2018-03-11 15:49:11'),
(125, 173, 'good', 0, '2018-03-11 15:50:11'),
(145, 173, 'bad', 0, '2018-03-11 15:51:11'),
(165, 173, 'bad', 0, '2018-03-11 15:52:11');
set @lastContentCheck = '';
set @lastHttpCode = '';
我可以编写以下查询来分配如上所述的组编号:
select
`id`,
`check_id`,
@groupNumber :=
case
when @lastContentCheck = `content_check` and @lastHttpCode = `http_code` then @groupNumber
else @groupNumber + 1
end as `GroupNumber`,
@lastContentCheck := `content_check` as `content_check`,
@lastHttpCode := `http_code` as `http_code`,
`time`
from
`data`,
(select @groupNumber := 0) as `gn`
where
`check_id` = 173
order by
`time`
该查询的输出是:
id check_id GroupNumber content_check http_code time
15 173 1 bad 0 2018-03-11 15:43:11
23 173 1 bad 0 2018-03-11 15:44:11
35 173 2 good 0 2018-03-11 15:45:11
49 173 2 good 0 2018-03-11 15:46:11
67 173 3 bad 0 2018-03-11 15:47:11
85 173 3 bad 0 2018-03-11 15:48:11
105 173 3 bad 0 2018-03-11 15:49:11
125 173 4 good 0 2018-03-11 15:50:11
145 173 5 bad 0 2018-03-11 15:51:11
165 173 5 bad 0 2018-03-11 15:52:11
此时,您只需在上面的查询周围包装另一个查询(按 GroupNumber
对其数据进行分组)即可获得所需的结果集。所以整个事情看起来像这样:
select
min(`id`) as `id`,
`check_id`,
`content_check`,
`http_code`,
min(`time`) as `EarliestTime`,
max(`time`) as `LatestTime`
from
(
select
`id`,
`check_id`,
@groupNumber :=
case
when @lastContentCheck = `content_check` and @lastHttpCode = `http_code` then @groupNumber
else @groupNumber + 1
end as `GroupNumber`,
@lastContentCheck := `content_check` as `content_check`,
@lastHttpCode := `http_code` as `http_code`,
`time`
from
`data`,
(select @groupNumber := 0) as `gn`
where
`check_id` = 173
order by
`time`
) as `GroupedData`
group by
`check_id`,
`GroupNumber`,
`content_check`,
`http_code`
order by
`GroupNumber`;
结果就是你想要的:
id check_id content_check http_code EarliestTime LatestTime
15 173 bad 0 2018-03-11 15:43:11 2018-03-11 15:44:11
35 173 good 0 2018-03-11 15:45:11 2018-03-11 15:46:11
67 173 bad 0 2018-03-11 15:47:11 2018-03-11 15:49:11
125 173 good 0 2018-03-11 15:50:11 2018-03-11 15:50:11
145 173 bad 0 2018-03-11 15:51:11 2018-03-11 15:52:11
关于mysql - SQL:按时间间隔按列分组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49237779/