计算来自不同游标的2个变量的总和--P1 / sql函数

时间:2011-09-07 15:45:27

标签: plsql cursor

我对pl / sql和编码相对较新,感谢您的帮助。有2个表如下。编写函数来计算日期范围的和(amt1)+和(amt2)。

我无法直接链接table1和table2,因为它会产生错误的结果。我有一个光标来计算table1的sum(amt1)和另一个光标来计算table2的sum(amt2)。如何从这两个光标计算sum(amt1)+ sum(amt2)

Table 1

Id  Amt Date
1   342 21-May-02
2   421 30-Mar-01
3   598 4-May-11
2   843 14-Jun-12
4   457 21-May-09
1   2346    24-Apr-98

Table 2


Id  Amt2    Date2
1   342 21-May-02
2   421 30-Mar-01
3   598 4-May-11
2   843 14-Jun-12
4   457 21-May-09
1   2346    24-Apr-98

这是我编译的函数,但是当我测试它时,它不会返回任何值

CREATE OR REPLACE FUNCTION FZ_HH_BY_DATE_COMMITMENT (pidm          number,
                                                     start_date    date,
                                                     end_date      date,
                                                     desg          varchar2)
   RETURN number
AS
     total_commit   number(13,2) := 0;
   total_gifts    number(13,2) := 0;
   total_pledges  number(13,2) := 0;
   sp_pidm        number (9);

  CURSOR date_commit_gifts IS
  SELECT SUM(azvglst_amt) FROM acu.azvglst
  WHERE  azvglst_pidm IN (pidm, sp_pidm)
  AND SUBSTR (azvglst_desg, 0, LENGTH (desg)) = desg
  AND azvglst_gift_date BETWEEN start_date AND end_date
  AND azvglst_pledge_no = '0000000'
  AND (azvglst_pgve_code <> '3P' OR azvglst_pgve_code IS NULL);


  CURSOR all_date_commit_gifts IS
  SELECT SUM(azvglst_amt) FROM acu.azvglst
  WHERE  azvglst_pidm IN (pidm, sp_pidm)
  AND azvglst_gift_date BETWEEN start_date AND end_date
  AND azvglst_pledge_no = '0000000'
  AND (azvglst_pgve_code <> '3P' OR azvglst_pgve_code IS NULL);


   CURSOR date_commit_pledges
   IS
      SELECT   SUM (agvplst_amt_pledged)
              FROM   agvplst
       WHERE   agvplst_pledge_date BETWEEN start_date AND end_date
               AND SUBSTR (agvplst_desg, 0, LENGTH (desg)) = desg
               AND agvplst_pidm IN (pidm, sp_pidm)
               AND agvplst_psta_code NOT IN ('I','C','U');

   CURSOR all_date_commit_pledges
   IS
      SELECT   SUM (agvplst_amt_pledged)
              FROM   agvplst
       WHERE   agvplst_pledge_date BETWEEN start_date AND end_date
                              AND agvplst_pidm IN (pidm, sp_pidm)
                              AND agvplst_psta_code NOT IN ('I','C','U');
BEGIN
   sp_pidm := TO_NUMBER (fz_split_fields (fz_spouse_info (pidm), 1));

   IF desg IS NULL
   THEN
      OPEN all_date_commit_gifts;
      FETCH all_date_commit_gifts INTO   total_gifts;
      CLOSE all_date_commit_gifts;

      OPEN all_date_commit_pledges;
      FETCH all_date_commit_pledges INTO total_pledges;
      CLOSE all_date_commit_pledges;

      ELSE OPEN date_commit_gifts;
      FETCH date_commit_gifts INTO   total_gifts;
      CLOSE date_commit_gifts;

      OPEN date_commit_pledges;
      FETCH date_commit_pledges INTO total_pledges;
      CLOSE date_commit_pledges;
      END IF;
      total_commit := total_gifts + total_pledges;
      RETURN total_commit;

END;

2 个答案:

答案 0 :(得分:1)

更新:

CREATE OR REPLACE FUNCTION CALC_BY_DATE(
    start_date DATE,
    end_date DATE)
    RETURN NUMBER
IS
  sum_amt NUMBER;
BEGIN
  SELECT SUM(AMT)
  INTO   sum_amt
  FROM   (
         SELECT AMT
         FROM   TABLE1
         WHERE  DATE >= start_date
         AND    DATE < end_date + 1
         UNION ALL
         SELECT AMT
         FROM   TABLE2
         WHERE  DATE >= start_date
         AND    DATE < end_date + 1
         );

  RETURN(NVL(sum_amt, 0));
END;

顺便说一句,如果你只是使用select ...而不是打开游标,fetch,close就可以了。

在一段时间之前,这在查询性能方面有所不同。

还有一件事

最可能的问题是这一行:

total_commit := total_gifts + total_pledges

你应该使用:

total_commit := NVL(total_gifts, 0) + NVL(total_pledges, 0)

请记住,如果你将任何东西加总为NULL,你就会得到NULL。

最好的问候。

答案 1 :(得分:0)

您无需使用两个游标:

select id, sum(amt) from
( select id, amt1 as amt from table1
  union all
  select id, amt2 as amt from table2
)
group by id