使用 plsql 进行回归编程以获得完美匹配

Regression programming using plsql for getting perfect match

我正在开发一个函数来从一组数字中获得完美匹配(最小值为 1,最大值为 25)。

我在下面给出了创建 table 的 DDL 以及我目前正在处理的插入语句和代码,这些代码存在性能问题。

运行 下面的代码。

如果记录数为 20,这将在 2 分钟内 运行。

我这里一共给出了33条记录,所以要花很多时间,不知道能不能完成。

任何输入都会有很大帮助。

CREATE TABLE xx_perfect_combi_test
(
  trx_id  NUMBER
 ,trx_val NUMBER
);

INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051303, 25);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051304, 25);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051305, 25);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051306, 24);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051307, 24);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051308, 24);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051309, 24);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051310, 23);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051311, 23);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051312, 23);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051313, 22);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051314, 22);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051315, 21);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051316, 21);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051317, 21);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051318, 20);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051319, 20);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051320, 20);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051321, 20);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051322, 18);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051323, 17);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051324, 11);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051325, 9);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051326, 8);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051327, 6);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051328, 6);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051329, 4);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051330, 3);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051331, 1);
INSERT INTO xx_perfect_combi_test (trx_id, trx_val) VALUES (2051332, 1);

COMMIT;

我的程序:

DECLARE
  ln_total_sum       NUMBER := 315;
  ln_orig_diff       NUMBER := ln_total_sum;
  ln_curr_diff       NUMBER;

  lv_trx_ids         VARCHAR2 (4000);
  lv_trx_ids_buff    VARCHAR2 (4000);

  lv_dummy_return    VARCHAR2 (4000);

  FUNCTION perfect_combo (p_curr_sum     IN NUMBER
                         ,p_curr_vals    IN VARCHAR2
                         ,p_rownumber    IN NUMBER)
    RETURN VARCHAR2
  IS
    lv_buf_trx_id    VARCHAR2 (4000);
  BEGIN
    FOR c1 IN (SELECT   *
               FROM (SELECT stg2.*
                           ,ROW_NUMBER () OVER (ORDER BY stg2.trx_val DESC) AS rownumber1
                     FROM xx_perfect_combi_test stg2)
                     WHERE rownumber1 > p_rownumber
                     ORDER BY trx_val DESC) LOOP
      --dbms_output.put_line ('p_curr_sum: ' || p_curr_sum);
      --dbms_output.put_line ('p_curr_vals: ' || p_curr_vals);
      --dbms_output.put_line ('p_rownumber: ' || p_rownumber);
      --dbms_output.put_line ('---------------------------------------------------');

      IF ( (p_curr_sum + c1.trx_val) = ln_total_sum)
      THEN
        lv_buf_trx_id  := p_curr_vals;
        lv_buf_trx_id  := lv_buf_trx_id || c1.trx_id || ';';
        lv_trx_ids     := lv_buf_trx_id;
        RETURN lv_trx_ids;
      ELSIF (p_curr_sum + c1.trx_val) > ln_total_sum
      THEN
        ln_curr_diff  := ln_total_sum - p_curr_sum;

        IF ln_curr_diff < ln_orig_diff
        THEN
          ln_orig_diff     := ln_curr_diff;
          lv_trx_ids_buff  := p_curr_vals;
        END IF;

        CONTINUE;
      ELSIF (p_curr_sum + c1.trx_val) < ln_total_sum
      THEN
        ln_curr_diff     := ln_total_sum - (p_curr_sum + c1.trx_val);

        lv_buf_trx_id    := p_curr_vals;
        lv_buf_trx_id    := lv_buf_trx_id || c1.trx_id || ';';

        IF ln_curr_diff < ln_orig_diff
        THEN
          ln_orig_diff     := ln_curr_diff;
          lv_trx_ids_buff  := lv_buf_trx_id;
        END IF;

        lv_dummy_return  := perfect_combo ( (p_curr_sum + c1.trx_val), lv_buf_trx_id, c1.rownumber1);
      END IF;
    END LOOP;

    RETURN NULL;
  END perfect_combo;
BEGIN
  lv_dummy_return  := perfect_combo (0, NULL, 0);

  DBMS_OUTPUT.put_line ('lv_trx_ids: ' || lv_trx_ids);
  DBMS_OUTPUT.put_line ('lv_trx_ids_buff: ' || lv_trx_ids_buff);
END;

我们必须在找到匹配项后完全退出函数调用。我已经创建了一个全局变量并检查是否找到匹配然后 return 完全来自函数调用。这样程序很快就完成了。