现在有一个系统他十四个子模块,要求的是这个系统的停止时间,现在在一个表中记录着每一个子模块的停止时间,只要有一个子模块停止了,表里就会多一条关于子模块停止的开始时间、结束时间和子模块代码的记录。子模块停止就代表系统停止。现在要求一个周内系统的停止的时间。请问这个逻辑应该怎么写。注意的是如果子模块1停止时间为八点到九点,子模块2停止的时间为八点半到九点半,那么系统的停止时间是八点到九点半,要排除重复时间,请大神表述的详细一点,本人小白,不太懂这个o(╯□╰)o
--看一下我理解的对不对
DECLARE
TYPE t_table IS TABLE OF 记录表%ROWTYPE;
v_data t_table;
v_second INTEGER:=0;
v_begin DATE;
v_end DATE;
BEGIN
SELECT * BULK COLLECT INTO v_data FROM 记录 ORDER BY 开始时间,结束时间 WHERE 开始时间>=sysdate-7;
FOR i IN 1..v_data.count LOOP
IF i=1 THEN
v_begin:=v_data(i).开始;
v_end:=v_data(i).结束;
ELSE
IF v_data(i).开始<v_data(i-1).结束 THEN
v_begin:=v_data(i-1).结束;
ELSE
v_begin:=v_data(i).开始;
END IF;
v_end:=v_data(i).结束;
END IF;
v_second:=(v_end-v_begin)*24*60*60+v_second;
END LOOP;
END;
急急急!拜托各位大神了!!小弟感激不尽!!!
所有子模块都停止,系统才算停止吗?
得确认:系统的停止时间是什么
1、如果系统的停止时间是指所有的模块都停止,最后一个模块停止时候的停止时间;
那么直接看数据库中是否有14条记录,如果有,那么根据结束时间(肯定含日期的)倒序排列获取第一条就好了,没有就是系统没停止。
2、如果系统的停止时间,是指每天最后一个停止模块的结束时间,那么
先将所有的停止时间按天归类,然后在每个分类中将结束时间倒序排列,取第一个 。如果某天内没有数据,就是当天系统没停止。
select min(开始时间),max(停止时间) from 记录表 where 开始时间>=sysdate-7
呵呵 那么简单吗? 我是不是理解错了
是不是区间问题? 比如1点到2点
5点到8点
10点到12点?
看你描述 应该是有时间间隔的是吗
先查询出来这一周内的记录 然后把开始时间和结束时间都取出来放到一个集合中进行时间判断
查询时按着开始时间排序
做一个排序,然后判断第二个开始时间是否在第一个的里面,如果在,直接取第二个的结束时间。 不在就分别计算。
SELECT SUM(times) FROM (
select b.*,case
when bd >= pre_end then
ed - bd
else
ed - pre_end
END AS times
from (select lag(a.ed, 1, a.bd) over(order by bd, bd) pre_end,a.*
from 表名 a
order by bd, ed) b)
对应sql可以这么写,用lag开窗函数 bd 开始时间 ed 结束时间
有点绕 可能还不如我上面写的代码块好理解
Oracle 存储过程可以解决:整体思路,不需要区分具体是哪个模块,把所有数据停止开始时间dtimes倒序进行遍历,记录最终开始日期maxdate和最终结束日期mindate,同事记录不存在的时候不交叉的时间段秒数removetime;最终用maxdate和mindate的秒数减去removetime的秒数,即为停止总时间(秒)。
==============存储过程===prm_today某天日期 参数格式2016-01-01 返回的是秒数 (查询一周的话自己改下代码即可,本例查询某天数据)========================
create or replace procedure TestDuan(prm_today IN VARCHAR2,PRM_allTime out NUMBER) is
maxdate date ;
mindate date;
removetime number;
temptime number;
temp number;
CURSOR CUR_TABLE IS
SELECT * FROM DTEST where dtimes >= to_date(prm_today||' 00:00:00','yyyy-mm-dd HH24:mi:ss')
and dtimee <= to_date(prm_today||' 00:00:00','yyyy-mm-dd HH24:mi:ss') order by dtimes;
begin
maxdate:=null;
maxdate:=null;
temp:=0;
removetime:=0;
FOR REC_table IN CUR_TABLE LOOP
if temp=0 then
temp:=1;
mindate := REC_table.Dtimes;
maxdate := REC_table.Dtimee;
end if;
if REC_table.Dtimes<=maxdate and REC_table.Dtimee<=maxdate then
removetime :=removetime;
elsif REC_table.Dtimes<=maxdate and REC_table.Dtimee>=maxdate then
maxdate :=REC_table.Dtimee;
elsif REC_table.Dtimes>=maxdate then
SELECT TO_NUMBER(REC_table.Dtimes-maxdate) * 24 * 60 * 60 into temptime FROM DUAL;
removetime :=removetime+temptime;
maxdate :=REC_table.Dtimee;
end if;
END LOOP;
SELECT TO_NUMBER(maxdate-mindate) * 24 * 60 * 60 into PRM_allTime FROM DUAL;
PRM_allTime:=PRM_allTime - removetime;
end TestDuan;
====================Table==================================
====================运行结果================================
如果你有模块的停止时间都保存在一个表中,支持 @qq221746 的回答
假定你有类A { start_time , end_time}
1、将数据库所有数据取出放到list;
2、定义一个LinkedList 用来存放最终处理之后的 无重复,无间隔的时间段 , 处理时保证时间段递增。
3、定义一个比较方法
compareA(A a,LinkedList b){
1、如果b的大小为0则将a放到b中
2、如果b的大小大于0,则将a的时间间隔依次与b中的进行比较
比较逻辑:a与b.get(i)比较 注意:**(int i=0;i<=b.size();) 这里最后i<=b.size(),是为了最后的处理,且i++要在逻辑中自己加**
1、如果a的结束时间小于b.get(i)的开始时间,则把a插入到b.get(i)的前面,return b。
2、如果a的开始时间大于b.get(i)的结束时间,
如果i=b.size()-1则将a插入到b的最后面,return b;
如果i<b.size()-1则i++进入下一个循环,
3、如果a与b.get(i)有交集,则将a与b.get(i)的时间集合求并集,将并集的开始结束时间赋值给a,然后从b中remove掉第i个元素,
然后直接进入下一个循环,不要进行i++
4、结束处理,如果i==b.size(),则将a添加到b的最后面
}
上面逻辑就这样了。 如果编码有什么问题,再询问。 希望对你有帮助!
如果你懂java的话,就使用下我下面的代码吧 。
package zzQuestions;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
public class TimeRemoveMulti {
/**
* 现在有一个系统他十四个子模块,要求的是这个系统的停止时间,
* 现在在一个表中记录着每一个子模块的停止时间,只要有一个子模块停止了,
* 表里就会多一条关于子模块停止的开始时间、结束时间和子模块代码的记录。
* 子模块停止就代表系统停止。现在要求一个周内系统的停止的时间。请问这个逻辑应该怎么写。
* 注意的是如果子模块1停止时间为八点到九点,子模块2停止的时间为八点半到九点半,
* 那么系统的停止时间是八点到九点半,要排除重复时间
* 系统的停止时间是如果一个子模块出现了停止,那么这个子模块的停止时间就要算到系统的停止时间里面,
* 最后要统计的是每周的工作时间,
* 所以不能是单纯的每个子模块的停止时间求和,要剔除各个子模块停止时间重复的部分
* @throws ParseException
*/
public static void main(String args[]) throws ParseException {
List<A> dataArray = new ArrayList<A>(); //存放数据库值
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dataArray.add(new A(df.parse("2016-9-10 11:23:24"), df.parse("2016-9-10 17:23:24")));
dataArray.add(new A(df.parse("2016-9-10 8:23:24"), df.parse("2016-9-10 13:23:24")));
dataArray.add(new A(df.parse("2016-9-11 11:23:24"), df.parse("2016-9-11 17:23:24")));
LinkedList<A> resultArray = new LinkedList<A>(); //存放最终无重复的时间段值
for (A a : dataArray) { //循环处理
compare(a, resultArray);
}
for (A a : resultArray) { //输出最后的记结果
System.out.println(df.format(a.getStartTime()) + "\t" + df.format(a.getEndTime()));
}
}
public static void compare(A a, LinkedList<A> resultArray) {
for (int i = 0; i <= resultArray.size();) {
//size为0或最终结束
if (i == resultArray.size()) {
resultArray.add(a);
return;
}
A b = resultArray.get(i);
//结束时间小于开始时间,插在前面返回,且不需要再与后面比较直接返回
if (a.getEndTime().before(b.getStartTime())) {
resultArray.add(i, a);
return;
}
//开始时间大于开始时间,i++进入下一次循环
if (a.getStartTime().after(b.getEndTime())) {
i++;
continue;
}
//a被b包含,则直接退出
if (a.getStartTime().after(b.getStartTime()) && a.getEndTime().before(b.getEndTime())) {
return;
}
//a将b的第i个元素包含或者2这有交集,则将并集付给A,并且从resultArray中移除B,然后进入下一次循环
{
Date startTime = a.getStartTime().compareTo(b.getStartTime()) > 0 ? b.getStartTime() : a.getStartTime();
Date endTime = a.getEndTime().compareTo(b.getEndTime()) > 0 ? a.getEndTime() : b.getEndTime();
a.setStartTime(startTime);
a.setEndTime(endTime);
resultArray.remove(i);
continue; //写了方便看
}
}
}
static class A {
private Date startTime;
private Date endTime;
public A(Date startTime, Date endTime) {
this.startTime = startTime;
this.endTime = endTime;
}
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
}
}
输出结果 :
2016-09-10 08:23:24 2016-09-10 17:23:24
2016-09-11 11:23:24 2016-09-11 17:23:24
亲,该结贴了吧? 我就等你的c币呢