qq_34906828 2016-09-12 08:32 采纳率: 33.3%
浏览 1426
已采纳

小白请教一个sql逻辑的问题,详见问题描述

现在有一个系统他十四个子模块,要求的是这个系统的停止时间,现在在一个表中记录着每一个子模块的停止时间,只要有一个子模块停止了,表里就会多一条关于子模块停止的开始时间、结束时间和子模块代码的记录。子模块停止就代表系统停止。现在要求一个周内系统的停止的时间。请问这个逻辑应该怎么写。注意的是如果子模块1停止时间为八点到九点,子模块2停止的时间为八点半到九点半,那么系统的停止时间是八点到九点半,要排除重复时间,请大神表述的详细一点,本人小白,不太懂这个o(╯□╰)o

  • 写回答

14条回答 默认 最新

  • qq221746 2016-09-12 09:19
    关注

    --看一下我理解的对不对
    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;

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
  • qq_34906828 2016-09-12 08:41
    关注

    急急急!拜托各位大神了!!小弟感激不尽!!!

    评论
  • qq221746 2016-09-12 08:43
    关注

    所有子模块都停止,系统才算停止吗?

    评论
  • 海_贼-王 2016-09-12 08:43
    关注

    得确认:系统的停止时间是什么

    1、如果系统的停止时间是指所有的模块都停止,最后一个模块停止时候的停止时间;
    那么直接看数据库中是否有14条记录,如果有,那么根据结束时间(肯定含日期的)倒序排列获取第一条就好了,没有就是系统没停止。

    2、如果系统的停止时间,是指每天最后一个停止模块的结束时间,那么
    先将所有的停止时间按天归类,然后在每个分类中将结束时间倒序排列,取第一个 。如果某天内没有数据,就是当天系统没停止。

    评论
  • qq221746 2016-09-12 08:48
    关注

    select min(开始时间),max(停止时间) from 记录表 where 开始时间>=sysdate-7

    呵呵 那么简单吗? 我是不是理解错了

    是不是区间问题? 比如1点到2点

    5点到8点

            10点到12点?
    
    评论
  • zhaihonghonghzh 2016-09-12 09:20
    关注

    看你描述 应该是有时间间隔的是吗
    先查询出来这一周内的记录 然后把开始时间和结束时间都取出来放到一个集合中进行时间判断

    评论
  • zhaihonghonghzh 2016-09-12 09:21
    关注

    查询时按着开始时间排序

    评论
  • 觅夜的黑 2016-09-12 09:32
    关注

    做一个排序,然后判断第二个开始时间是否在第一个的里面,如果在,直接取第二个的结束时间。 不在就分别计算。

    评论
  • qq221746 2016-09-12 10:02
    关注

    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 结束时间   
                有点绕  可能还不如我上面写的代码块好理解
    
    评论
  • Mop.Duan 2016-09-12 10:42
    关注

    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==================================
    图片说明
    ====================运行结果================================
    图片说明

    评论
  • 微wx笑 Java领域优质创作者 2016-09-12 23:25
    关注

    如果你有模块的停止时间都保存在一个表中,支持 @qq221746 的回答

    评论
  • 海_贼-王 2016-09-13 00:59
    关注
    评论
  • 海_贼-王 2016-09-13 02:35
    关注

    如果你懂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

    评论
  • qq221746 2016-09-14 07:56
    关注

    亲,该结贴了吧? 我就等你的c币呢

    评论
查看更多回答(13条)

报告相同问题?

悬赏问题

  • ¥15 vue+element 生成table
  • ¥15 实验 4 FIFO 算法和 LRU 算法-C 程序实现
  • ¥30 电脑画面同步投屏,通过同wifi的方式投屏方法,接收投屏端不需要安装第三方软件,
  • ¥15 有偿拼接大疆精灵4RGB影像
  • ¥15 MATLAB特殊符号
  • ¥15 Arduino实现音频混响
  • ¥15 cuda.jit加速报错
  • ¥15 Octave 安装工具箱出错 Only Win32 target is supported!
  • ¥15 docker save的不能在另一台设备运行
  • ¥15 Unity Animation Rigging使用问题