牛B的存储过程

DROP PROCEDURE IF EXISTS `demo3`;

CREATE DEFINER = `root`@`localhost` PROCEDURE `demo3`(OUT `bilv` double)
BEGIN

DECLARE arg_id INT DEFAULT 49;
DECLARE start VARCHAR(30) DEFAULT '2012-06-29 00.00.00';
DECLARE end VARCHAR(30) DEFAULT '2012-07-20 23.59.59';
DECLARE f int DEFAULT -1;-- 不能删除 与业务无关 操蛋之极
DECLARE x BIGINT;-- 转换成long型 运算时间  这个时间是(秒)为单位
DECLARE t VARCHAR(30);-- 时间
DECLARE d_id INT;-- 设备id
DECLARE id INT;--  这条数据  id
DECLARE state INT; -- 上下线状态值
DECLARE ii BIGINT DEFAULT 0;
DECLARE i int;
DECLARE linshi BIGINT; --  临时获取 一次上线过后 最近的一次下线
DECLARE linshi2 BIGINT DEFAULT 0; --  该变量默认值为0不能更改  在之后程序中有为null 判断参与业务判断,此次变量定义 为解决 当 循环查询中 查询出 null 数据时候 并不会赋值给 INTO linshi 所以无法判断 是否已经循环到最后一条数据了 并且 最后一条数据还是 上线数据
DECLARE sums INT; -- 查出限定范围内的上线次数
-- 查询 限定返回内 不分 上线 下线 的 所有数据 日期最早的一条
DECLARE all_obj CURSOR for select d.id,d.device_at,d.device_id,d.device_state,UNIX_TIMESTAMP(d.device_at) from _device_action_logger d where 1=1 and d.device_at BETWEEN STR_TO_DATE(start,'%Y-%m-%d %k.%i.%s') and STR_TO_DATE(end,'%Y-%m-%d %k.%i.%s') and device_id=arg_id order by d.device_at asc limit 1;
-- 查询 限定返回内 不分 上线 下线 的 所有数据 日期最晚 的一条
DECLARE all_obj1 CURSOR for select d.id,d.device_at,d.device_id,d.device_state,UNIX_TIMESTAMP(d.device_at) from _device_action_logger d where 1=1 and d.device_at BETWEEN STR_TO_DATE(start,'%Y-%m-%d %k.%i.%s') and STR_TO_DATE(end,'%Y-%m-%d %k.%i.%s') and device_id=arg_id order by d.device_at DESC limit 1;
-- 查询 时间段内 所有 上线 数据
DECLARE obj CURSOR for  select UNIX_TIMESTAMP(device_at),device_at,device_id,d1.id from _device_action_logger d1 where 1=1 and d1.device_at BETWEEN STR_TO_DATE(start,'%Y-%m-%d %k.%i.%s') and STR_TO_DATE(end,'%Y-%m-%d %k.%i.%s') and device_state=0 and device_id=arg_id ORDER BY device_at ASC;
-- 查询上线数据总数 用于 REPEAT 循环
DECLARE o CURSOR for select count(*) from _device_action_logger d1 where 1=1 and d1.device_at BETWEEN STR_TO_DATE(start,'%Y-%m-%d %k.%i.%s') and STR_TO_DATE(end,'%Y-%m-%d %k.%i.%s') and d1.device_state=0 and device_id=arg_id;
-- 还没搞清楚 撒玩意 暂时不扔
DECLARE CONTINUE HANDLER for not found  set f=1;

-- 判断 第一条 是否 下线数据
open all_obj;
FETCH all_obj into id,t,d_id,state,x;
CASE state
WHEN 1 then
-- 如果查询时间段内 第一条记录 是下线的 那么这次 上线的时间长度 就以 开始时间作为此次 上线的时间点 两时间做运算
set ii=ii+x-UNIX_TIMESTAMP(start);
WHEN 0 THEN
set ii=ii;  -- 如果 第一条记录 是上线 这不做操作 马屁的 这一排 必须要做点操作 所以写了 set ii=ii; 这步是废材
ELSE
-- 如果 出现 查询时间段内 没有上线下线 那么 查询 start 之前 最近 一条记录 是 上线 则判断 为 此次查询时间段内 全部,在线 。反正 则 不存在,在线
select device_state INTO state from _device_action_logger d where 1=1 and device_at < STR_TO_DATE(start,'%Y-%m-%d %k.%i.%s') and device_id=arg_id ORDER BY device_at DESC LIMIT 1;
CASE state
when 0 THEN
set bilv=1;
when 1 THEN
set bilv=0;
ELSE
set bilv=1;
end CASE;
end CASE;
CLOSE all_obj;

-- 判断 最后一条数据 是否 上线数据
OPEN all_obj1;
FETCH all_obj1 INTO id,t,d_id,state,x;
CASE state
WHEN 1 THEN
-- 最后一条记录 是下线 不做操作  马屁的 这一排 必须要做点操作 所以写了 set ii=ii; 这步是废材
set ii=ii;
WHEN 0 THEN
-- 最后一条操作 是上线  则这次上线的时间长度 等于  上线 时间 与 end 两运算
set ii=ii+UNIX_TIMESTAMP(end)-x;
ELSE
-- 空操作
set ii=ii;
end CASE;
CLOSE all_obj1;

OPEN o;
FETCH o INTO sums;
CLOSE o;

-- 设定循环变量自增 数
set i=1;

if sums <>0 then
open obj;
REPEAT  
FETCH obj into x,t,d_id,id;
--  小问题  t 生成的时间 时分秒 是 :间隔  所以 后面 注意
select UNIX_TIMESTAMP(device_at) into linshi  from _device_action_logger d2 where 1=1 and device_at BETWEEN STR_TO_DATE(t,'%Y-%m-%d %k:%i:%s') and STR_TO_DATE(end,'%Y-%m-%d %k.%i.%s') and device_state=1 and device_id=arg_id ORDER BY  device_at  ASC LIMIT 1;
select i,linshi,linshi2;
if linshi <>linshi2 THEN
set ii=ii+linshi-x;
select i, ii;
ELSE
set ii=ii; -- 空操作
select '最后一次',ii;
 END IF;
set linshi2=linshi;
set i=i+1;
until i>sums
end REPEAT;
CLOSE obj;
ELSE
set sums=sums;
END IF;
-- 运算这段时间内在线比率
set bilv=ii/(UNIX_TIMESTAMP(end)-UNIX_TIMESTAMP(start));
select bilv ,ii ;
END;


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值