首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 请教各位高手,这个统计的存储过程该怎么写呀? [已结贴,结贴人:pass2005]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • pass2005
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 揭贴率:
    发表于:2008-08-18 19:51:47 楼主
    我有一个表test,有如下字段(和记录):
      addTime(日期)      A(字段A) B(字段B) C(字段C)
      2008-8-1              20        30        40
      2008-8-2              10        30        40
      2008-8-3              13        39        56
      2008-8-4              25        56        43
      2008-8-5              36        30        25
      2008-8-6              20        36        67
      2008-8-7              20        90        40

    字段addtime为日期型
    其余为number型

    我需要用存储过程求出一个月汇总和一个年汇总

    月汇总的在页面上显示是:
      月份      month_A  month_B  month_C
      2008-8    200        90      200
      2008-9    0          0        0

    其中:month_A 是指定月份A 字段值的求和
          month_B 是指定月(有记录的)B字段最后一天的值,例如现在数据的8月份最大的日期是8月7号,所2008-8-7是8月最后一天记录。
          month_C和month_A 是类似的。

      这个月份会是一个参数,到时候是动态的,可以动态显示不同的月份,或者是多个月份的。


    年汇总比月汇总还麻烦一点:
        年份        year_A  year_B  year_C
      2008年        200        90      200
      2009年          100      40        37

    year_A 指定年份说有A字段的求和
    year_B 指定年份B字段最后一天的值
    year_C 指定年份中C字段到目前(有记录)月份最后一天值得求和。这个最麻烦,要分别把数据库里本年度的每个月最后一天的值求和。

    这个年份也是一个参数,为空的话,就是显示库中有记录的所有年份。

    想用各用存储过程,分别把年汇总和月汇总能拼成这样一个数据集,请大家帮忙。
    100  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hebo2005
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 3

      2

    发表于:2008-08-18 20:48:561楼 得分:90
    SQL可以写出来,要写存储过程返回数据集,麻烦点

    月的,我先写一段,你可以参考下

    WITH TEST AS
        (SELECT TO_DATE ('2008-8-1', 'yyyy-mm-dd') addtime, 20 a, 30 b, 40 c
            FROM DUAL
          UNION ALL
          SELECT TO_DATE ('2008-8-2', 'yyyy-mm-dd') addtime, 10, 30, 40
            FROM DUAL
          UNION ALL
          SELECT TO_DATE ('2008-8-3', 'yyyy-mm-dd') addtime, 13, 39, 56
            FROM DUAL
          UNION ALL
          SELECT TO_DATE ('2008-8-4', 'yyyy-mm-dd') addtime, 25, 56, 43
            FROM DUAL
          UNION ALL
          SELECT TO_DATE ('2008-8-5', 'yyyy-mm-dd') addtime, 36, 30, 25
            FROM DUAL
          UNION ALL
          SELECT TO_DATE ('2008-8-6', 'yyyy-mm-dd') addtime, 20, 36, 67
            FROM DUAL
          UNION ALL
          SELECT TO_DATE ('2008-8-7', 'yyyy-mm-dd') addtime, 20, 90, 40
            FROM DUAL)
    SQL code
    SELECT m.months, NVL (t.months_a, 0) months_a, NVL (months_b, 0) months_b, NVL (months_c, 0) months_c FROM (SELECT TO_CHAR (ADD_MONTHS (TO_DATE (:start_date, 'yyyy-mm'), ROWNUM - 1 ), 'yyyy-mm' ) months FROM all_objects WHERE ROWNUM <= MONTHS_BETWEEN (TO_DATE (:end_date, 'yyyy-mm'), TO_DATE (:start_date, 'yyyy-mm') ) + 1) m, (SELECT TO_CHAR (addtime, 'yyyy-mm') months, SUM (a) months_a, months_b, SUM (c) months_c FROM (SELECT a.*, LAST_VALUE (b) OVER (PARTITION BY TO_CHAR (addtime, 'yyyy-mm' ) ORDER BY addtime ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) months_b FROM TEST a WHERE addtime BETWEEN TO_DATE (:start_date, 'yyyy-mm') AND TO_DATE (:end_date, 'yyyy-mm') + 0.99999) GROUP BY TO_CHAR (addtime, 'yyyy-mm'), months_b) t WHERE m.months = t.months(+)


    结果
    Row# MONTHS MONTHS_A MONTHS_B MONTHS_C

    1 2008-08 144 90 311
    2 2008-09 0 0 0
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hebo2005
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 3

      2

    发表于:2008-08-18 20:54:152楼 得分:0
    年可以在月求和的基础上再求次和
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • pass2005
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-18 21:19:243楼 得分:0
    多谢楼上的,不过我没看明白思路。
    SELECT m.months, NVL (t.months_a, 0) months_a, NVL (months_b, 0) months_b,
          NVL (months_c, 0) months_c
      FROM (SELECT TO_CHAR (ADD_MONTHS (TO_DATE (:start_date, 'yyyy-mm'),
                      ADD_MONTHS --这个好像不是个函数吧           
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • pass2005
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-18 21:22:294楼 得分:0
    FROM all_objects,这个all_objects是什么意思呀?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • pass2005
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-18 21:41:015楼 得分:0
    all_objects我查的下有的说是视图,有点说是系统表,到底是啥呀
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hebo2005
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 3

      2

    发表于:2008-08-18 21:48:076楼 得分:5
    是系统表
    如果不能访问此表
    可以用以下语句代替
    SQL code
    SELECT TO_CHAR (ADD_MONTHS (TO_DATE (:start_date, 'yyyy-mm'), ROWNUM - 1 ), 'yyyy-mm' ) months FROM dual connect by ROWNUM <= MONTHS_BETWEEN (TO_DATE (:end_date, 'yyyy-mm'), TO_DATE (:start_date, 'yyyy-mm') ) + 1
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hebo2005
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 3

      2

    发表于:2008-08-18 21:50:097楼 得分:5
    这段是生成查询月份
    其实你也可以不需要
    主要是为了生成可能部分月没有数据,比如测试数据没有2008-09的数据,但查询区间有9月份的
    就时候就显示如我做测试的结果集
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • pass2005
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-18 22:00:158楼 得分:0
    多谢这位兄弟,我研究下你的写法,有问题再请教。能帮我弄个存储过程版的么,用存储过程应该效率高点。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • pass2005
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-18 22:10:199楼 得分:0
          (SELECT  TO_CHAR (addtime, 'yyyy-mm') months, SUM (a) months_a,
                    months_b, SUM (c) months_c
                FROM (SELECT a.*,
                            LAST_VALUE (b) OVER (PARTITION BY TO_CHAR
                                                                (addtime,
                                                                  'yyyy-mm'
                                                                ) ORDER BY addtime ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
                                                                        months_b
                        FROM TEST a
                      WHERE addtime BETWEEN TO_DATE (:start_date, 'yyyy-mm')
                                        AND  TO_DATE (:end_date, 'yyyy-mm')
                                            + 0.99999)
    这段没太明白,尤其最后这个+0、99999,很少见过。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hebo2005
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 3

      2

    发表于:2008-08-18 22:12:4010楼 得分:0
    +0.99999就是当天的23:59:59
    当然也可以用 <TO_DATE (:end_date, 'yyyy-mm') +1
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • pass2005
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 11:35:3911楼 得分:0
    还有别的高手现身么!!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • pass2005
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-29 15:11:4612楼 得分:0
      addTime(日期)      A(字段A) B(字段B) C(字段C)  typename
      2008-8-1              20        30        40      x
      2008-8-2              10        30        42      x
      2008-8-1              11        32        44      y
      2008-8-2              12        33        45      y
      2008-8-3              13        39        56      x
      2008-8-4              25        56        43      y
      2008-8-5              36        30        25      y
      2008-8-6              20        36        67      y
      2008-8-7              20        90        40      x
      2008-8-7              30        24        23      z
    现在我的这汇总比原来又复杂了一点,多了个字段typename,里面有不同的值,汇总要按照这个typename进行区分。
    如:月汇总会是:
    月份      month_A  month_B  month_C  typename
      2008-8    200        90      200    x
      2008-8    223        0        0      y
      2008-9    200        90      200    x
      2008-9    34        0        0      y

    这样
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • dobetterthatnthink
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-29 15:38:4413楼 得分:0
    这个简单的算法,好像不怎么具有研究的价值啊。
    就是用最老土,最笨的犯法,也可以一步步搞定。
    ---特别是如果对性能没有苛刻要求的情况下。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • pass2005
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-29 15:45:3214楼 得分:0
    楼上的兄弟,能说具体点么
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • mantisXF
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 2

    发表于:2008-08-29 15:48:3815楼 得分:0
    存储过程的总体性能会比SQL高思想是不正确的,反而在大多数情况下SQL性能会好些因为是集合化的处理.

    引用 8 楼 pass2005 的回复:
    多谢这位兄弟,我研究下你的写法,有问题再请教。能帮我弄个存储过程版的么,用存储过程应该效率高点。

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • pass2005
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-29 16:02:1016楼 得分:0
    addTime(日期)      A(字段A) B(字段B) C(字段C)  typename
      2008-8-1              20        30        40      x
      2008-8-2              10        30        42      x
      2008-8-1              11        32        44      y
      2008-8-2              12        33        45      y
      2008-8-3              13        39        56      x
      2008-8-4              25        56        43      y
      2008-8-5              36        30        25      y
      2008-8-6              20        36        67      y
      2008-8-7              20        90        40      x
      2008-8-7              30        24        23      z
    现在我的这汇总比原来又复杂了一点,多了个字段typename,里面有不同的值,汇总要按照这个typename进行区分。
    如:月汇总会是:
    月份      month_A  month_B  month_C  typename
      2008-8    200        90      200    x
      2008-8    223        0        0      y
      2008-9    200        90      200    x
      2008-9    34        0        0      y

    请大家帮忙回答下这个问题,能不能在hebo2005 sql上进行改造
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hebo2005
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 3

      2

    发表于:2008-08-29 16:38:5317楼 得分:0
    SQL code
    SELECT m.months, NVL (t.months_a, 0) months_a, NVL (months_b, 0) months_b, NVL (months_c, 0) months_c,typename FROM (SELECT TO_CHAR (ADD_MONTHS (TO_DATE (:start_date, 'yyyy-mm'), ROWNUM - 1 ), 'yyyy-mm' ) months FROM all_objects WHERE ROWNUM <= MONTHS_BETWEEN (TO_DATE (:end_date, 'yyyy-mm'), TO_DATE (:start_date, 'yyyy-mm') ) + 1) m, (SELECT TO_CHAR (addtime, 'yyyy-mm') months, SUM (a) months_a, months_b, SUM (c) months_c,typename FROM (SELECT a.*, LAST_VALUE (b) OVER (PARTITION BY TO_CHAR (addtime, 'yyyy-mm' ),typename ORDER BY addtime ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) months_b FROM TEST a WHERE addtime BETWEEN TO_DATE (:start_date, 'yyyy-mm') AND TO_DATE (:end_date, 'yyyy-mm') + 0.99999) GROUP BY TO_CHAR (addtime, 'yyyy-mm'), months_b,typename ) t WHERE m.months = t.months(+)
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • pass2005
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-29 16:43:1518楼 得分:0
    呵呵,多谢哥们
    修改 删除 举报 引用 回复

    网站简介广告服务网站地图帮助联系方式诚聘英才English 问题报告
    北京创新乐知广告有限公司 版权所有 京 ICP 证 070598 号
    世纪乐知(北京)网络技术有限公司 提供技术支持
    Copyright © 2000-2008, CSDN.NET, All Rights Reserved