使用 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 完全来自函数调用。这样程序很快就完成了。
我正在开发一个函数来从一组数字中获得完美匹配(最小值为 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 完全来自函数调用。这样程序很快就完成了。