昨天的问题没有彻底的解决,就是没有值的时候显示0,还望朋友们在帮忙想想假设我有张表DetectionRate(缺陷率),表里有字段Error(缺陷),CjQty(抽检数量),NotOKQty(不合格数),Tdate(时间)。
如何去实现:假设日期从2009-01-01至2010—01-01这段时间内(这个时间段是可变的,也就是某个时间段内),日期间隔N天,查询出Error(缺陷)的不合格率。
这里的日期间隔N天是这样解释的,就是说以上时间段内(2009-01-01至2010—01-01),假设日期间隔是10天,也就是说2009—01—01至2009—01—10这个时间段内Error(缺陷)
的不合格率(不合格数/抽检数),以此类推2009—01—11至2009—01—20,2009—01—21至2009—01—30.我建张表好理解一点,如下表:
假设初始表:
  Error         CjQty    NotOKQty      Tdate
装配件错误       300        5         2009-01-01
装配件错误       350        7         2009-01-05
装配件错误       400        8         2009-01-10
装配件错误       400        2         2009-01-15
装配件错误       350        5         2009-01-20
装配件错误       350        7         2009-03-20按需求得到后的表是:  Error          Rate            Mdate
装配件错误      20/1050     2009-01-01至2009-01-10
装配件错误      7/750       2009-01-11至2009-01-20
装配件错误       0          2009-01-21至2009-01-30
装配件错误       0          2009-01-31至2009-02-09
装配件错误       0          2009-02-10至2009-02-19
装配件错误       0          2009-02-20至2009-03-01
装配件错误       0          2009-03-02至2009-03-11
装配件错误      7/350       2009-03-12至2009-03-21
装配件错误      0                    。
装配件错误      0                    。
装配件错误      0                    。
装配件错误      0                    。
装配件错误      0           。。至2010-01-01
这个不合格率就是在日期间隔interval内,总的不合格数/总的抽检数*100%,以上的Rate为了显示效果没算出百分率来,如果在时间间隔内没有
值那么不合格率就是0(一定要这个效果出来)。总的来说就是有三个参数,日期自dateFrom,日期至dateTo,日期间隔interval来写个存储过程,希望大家能帮小弟个忙,
刚学存储过程不是很熟悉,谢谢大家了!

解决方案 »

  1.   

    昨天帮忙解决问题的archwuke1,可以在帮忙吗
      

  2.   

    我想可以分两步来做,
    第一步:将需要查询的时间段用程序控制分成分成相应的区间,比如 (2009-01-01至2010—01-01),假设日期间隔是10天,则是2009—01—01至2009—01—10,2009—01—11至2009—01—20.....
    第二步,对每个区间求缺陷率,具体方法如下:
    select Error,  (count(NotOKQty)/  count(CjQty)) * 100
    from  DetectionRate
    where Tdate >= 开始时间
    and Tdate < 截止时间 
    group by  Error     
      

  3.   

    如5楼所说,先用sql语句取得时间分段数据(ta),然后左连接我上次发的的语句的结果(tb)再对结果进行微调应该就差不多了
    因为我对你的表的具体情况不太了解
    我先写一个大致的语句在这里SELECT * FROM 
    (select to_date('2009-01-01','yyyy-mm-dd')+(rownum-1)*10 自,to_date('2009-01-01','yyyy-mm-dd')+ROWNUM*10 至 from dual connect by rownum <=7) ta
    left JOIN
    (SELECT ERROR,
           TO_DATE('2009-01-1', 'yyyy-mm-dd') + (AA - 1) * 10 自,
           TO_DATE('2009-01-1', 'yyyy-mm-dd') + AA * 10 至,
           BB,
           CC
      FROM (SELECT ERROR,
                   CEIL((TDATE - TO_DATE('2009-01-01', 'yyyy-mm-dd') + 1) / 10) AA,
                   SUM(NOTOKQYT) BB,
                   SUM(CJQTY) CC
              FROM RATE
             WHERE TDATE BETWEEN TO_DATE('2009-01-01', 'yyyy-mm-dd') AND
                   TO_DATE('2009-07-05', 'yyyy-mm-dd')
             GROUP BY ERROR,
                      CEIL((TDATE - TO_DATE('2009-01-01', 'yyyy-mm-dd') + 1) / 10)))tb
    ON ta.自=tb.自 AND ta.至=tb.至;
      

  4.   

    再取 select distinct error from DetectionRate 来联接下应该就可以了
      

  5.   

    从2009-1-1至2010-1-31是396天,每个错误有40条记录
    我也是新学,不知道写得对不对,你试试吧SELECT TA.*, NVL(TB.BB, 0) 不良品数, NVL(TB.CC, 0) 检查数
      FROM (SELECT *
              FROM (SELECT TO_DATE('2009-01-01', 'yyyy-mm-dd') + (ROWNUM - 1) * 10 自,
                           TO_DATE('2009-01-01', 'yyyy-mm-dd') + ROWNUM * 10 至
                      FROM DUAL
                    CONNECT BY ROWNUM <=
                               CEIL((TO_DATE('2010-01-31', 'yyyy-mm-dd') -
                                    TO_DATE('2009-01-01', 'yyyy-mm-dd')) / 10)) TAA,
                   (SELECT DISTINCT ERROR FROM RATE) TCC) TA
      LEFT JOIN (SELECT ERROR,
                        TO_DATE('2009-01-1', 'yyyy-mm-dd') + (AA - 1) * 10 自,
                        TO_DATE('2009-01-1', 'yyyy-mm-dd') + AA * 10 至,
                        BB,                CC
                   FROM (SELECT ERROR,
                       CEIL((TDATE - TO_DATE('2009-01-01', 'yyyy-mm-dd') + 1) / 10) AA,
                                SUM(NOTOKQYT) BB,
                                SUM(CJQTY) CC
                           FROM RATE
                          WHERE TDATE BETWEEN TO_DATE('2009-01-01', 'yyyy-mm-dd') AND
                                TO_DATE('2010-01-31', 'yyyy-mm-dd')
                          GROUP BY ERROR,
                                   CEIL((TDATE -
                                      TO_DATE('2009-01-01', 'yyyy-mm-dd') + 1) / 10))) TB
        ON TA.自 = TB.自   AND TA.至 = TB.至   AND TA.ERROR = TB.ERROR
     ORDER BY TA.ERROR, TA.自;
      

  6.   

    用笛卡尔积建个视图,外连接你的表。写完代码看到了archwuke1的回复,大致思路差不多
    也贴上来参考下吧
    create or replace procedure protest(begin_date in date,
                                        end_date   in date,
                                        interval   in number,
                                        cur        out sys_refcursor) as
    begin
      open cur for
        select a.error,
               nvl(sum(b.notokqty), 0) || '/' || nvl(sum(b.cjqty), 0) rate,
               to_char(a.begin_date, 'yyyy-mm-dd') || '至' ||
               to_char(a.end_date, 'yyyy-mm-dd') mdate
          from (select *
                  from (select begin_date + interval * (rownum - 1) begin_date,
                               case
                                 when begin_date + rownum * interval - 1 >
                                      end_date then
                                  end_date
                                 else
                                  begin_date + interval * rownum - 1
                               end end_date
                          from dual
                        connect by rownum <
                                   (end_date - begin_date) / interval + 1),
                       (select distinct error from DetectionRate)) a,
               DetectionRate b
         where b.tdate(+) between a.begin_date and a.end_date
           and a.error = b.error(+)
         group by a.error,
                  to_char(a.begin_date, 'yyyy-mm-dd'),
                  to_char(a.end_date, 'yyyy-mm-dd')
         order by 1, 3;
    end;
      

  7.   

    简化一下SELECT TA.*, (SELECT nvl(SUM(notokqyt),0) FROM rate WHERE tdate BETWEEN ta.自 AND ta.至 AND ERROR=ta.error)
    ,(SELECT NVL(SUM(cjqty),0) FROM rate WHERE tdate BETWEEN ta.自 AND ta.至 AND ERROR=ta.error)
      FROM (SELECT *
              FROM (SELECT TO_DATE('2009-01-01', 'yyyy-mm-dd') + (ROWNUM - 1) * 10 自,
                           TO_DATE('2009-01-01', 'yyyy-mm-dd') + ROWNUM * 10 至
                      FROM DUAL
                    CONNECT BY ROWNUM <=
                               CEIL((TO_DATE('2010-01-31', 'yyyy-mm-dd') -
                                    TO_DATE('2009-01-01', 'yyyy-mm-dd')) / 10)) TAA,
                   (SELECT DISTINCT ERROR FROM RATE) TCC) TA
     ORDER BY TA.ERROR, TA.自;
     
      

  8.   

    --2009-01-01 起始日期 , 2009-03-31 结束日期 , 10 为每10天, 可照此修改
    SELECT error,
           nvl(round(SUM(notokqty) / SUM(cjqty), 3), 0) notokrate,
           to_char(bdate, 'yyyy-mm-dd') || '/' || to_char(edate, 'yyyy-mm-dd')
      FROM (SELECT b.error, a.cjqty, a.notokqty, b.bdate, b.edate
              FROM DetectionRate a
             RIGHT JOIN (SELECT a.error, b.bdate, b.edate
                          FROM (SELECT DISTINCT error FROM DetectionRate) a,
                               (SELECT DATE '2009-01-01' + (LEVEL - 1) * 10 bdate,
                                       DATE '2009-01-01' + (LEVEL - 1) * 10 + 10 - 1 edate
                                  FROM dual
                                CONNECT BY LEVEL <
                                           ceil((DATE '2009-03-31' - DATE '2009-01-01' + 1) / 10) + 1) b) b
                ON (a.tdate BETWEEN b.bdate AND b.edate AND a.error = b.error))
     GROUP BY error, bdate, edate
     ORDER BY error
      

  9.   

    我觉得不用那么复杂,我写group by 的用意就是对应多个错误的。
      

  10.   

    最近出差去了,现在才回来结贴,不好意思啊,感谢各位的帮助,特别是archwuke1和wildwave的帮助