【发布时间】:2018-02-22 13:00:40
【问题描述】:
我们有售货亭供客户检查他们购买的两种不同类别商品的数量。他们将输入他们的手机号码,这将向他们的手机号码发送一个 OTP,然后他们将输入回验证,系统必须检查数据并为他们显示。作为开发人员,kiosk 供应商为我们提供了一个功能有限的开发工具包,我们可以通过它对数据库执行 select 语句并在 kiosk 上显示返回值。
我创建了一个对象类型如下:
CREATE OR REPLACE TYPE rebate_values
AS
OBJECT (ASales_total number,
ACurrent_Rebate_Percent number,
ANeeded_Sales number,
ANext_Rebate_Percent number,
BSales_total number,
BCurrent_Rebate_Percent number,
BNeeded_Sales number,
BNext_Rebate_Percent number);
我将通过客户手机获取他们的销售和返利信息的功能:
CREATE OR REPLACE FUNCTION AA_rebate_function (P_phone IN NUMBER)
RETURN rebate_values
IS
A_P_Sales_total NUMBER;
A_P_Current_Rebate_Percent NUMBER;
A_P_Needed_Sales NUMBER;
A_P_Next_Rebate_Percent NUMBER;
B_P_Sales_total NUMBER;
B_P_Current_Rebate_Percent NUMBER;
B_P_Needed_Sales NUMBER;
B_P_Next_Rebate_Percent NUMBER;
P_CODE VARCHAR (10);
BEGIN
SELECT CC_CODE
INTO P_CODE
FROM CUSTOMERS
WHERE C_MOBILE = P_phone;
FOR OUTDATA
IN (
--My Query to retrieve the data
Select ................
)
LOOP
IF OUTDATA.CLASS = 'X'
THEN
A_P_Sales_total := OUTDATA.SALES_TOTAL;
A_P_Current_Rebate_Percent := OUTDATA.CURRENT_REBATE_PERCENT;
A_P_Needed_Sales := OUTDATA.NEEDED_SALES_FOR_HIGHER_REBATE;
A_P_Next_Rebate_Percent := OUTDATA.NEXT_HIGHER_REBATE_PERCENT;
END IF;
IF OUTDATA.CLASS = 'Y'
THEN
B_P_Sales_total := OUTDATA.SALES_TOTAL;
B_P_Current_Rebate_Percent := OUTDATA.CURRENT_REBATE_PERCENT;
B_P_Needed_Sales := OUTDATA.NEEDED_SALES_FOR_HIGHER_REBATE;
B_P_Next_Rebate_Percent := OUTDATA.NEXT_HIGHER_REBATE_PERCENT;
END IF;
END LOOP;
RETURN rebate_values (A_P_Sales_total,
A_P_Current_Rebate_Percent,
A_P_Needed_Sales,
A_P_Next_Rebate_Percent,
B_P_Sales_total,
B_P_Current_Rebate_Percent,
B_P_Needed_Sales,
B_P_Next_Rebate_Percent);
END;
/
查询需要 27 秒来检索每个客户的值。每个客户将有 2 行,这就是我使用 LOOP 来收集值的原因。
当我执行函数时:
SELECT AA_rebate_function (XXXXXXXXXX) FROM DUAL;
我在 27 秒内得到单列数据如下:
(XXXX, X, XXXX, X, XXXX, X, XXXX, X)
但是当我执行该函数以获取不同列中的值时,需要 27 x 8 秒 = 216 秒,即大约 3.6 分钟,这是一个大问题,因为客户无法在自助服务终端上等待 3.6 分钟才能查看数据。
SELECT x.c.ASales_total,
x.c.ACurrent_Rebate_Percent,
x.c.ANeeded_Sales,
x.c.ANext_Rebate_Percent,
x.c.BSales_total,
x.c.BCurrent_Rebate_Percent,
x.c.BNeeded_Sales,
x.c.BNext_Rebate_Percent
FROM (SELECT AA_rebate_function (XXXXXXXXXX) c FROM DUAL) x;
我尝试使用带有OUT 值的存储过程,但它不适合我的环境,因为我无法通过 kiosk 开发工具包编程执行存储过程,因为它只支持选择语句,与供应商核实过,但他们不'没有任何计划在不久的将来添加该支持。
我尝试使用 REGEXP_SUBSTR 将单个字段转换为多个列,但由于它是一个数组,因此出现类型转换错误。
查询很复杂,要计算最近10年的数据,有几百万行,27秒其实是得到想要的结果的最佳时间。
【问题讨论】:
-
简化您的问题并创建一个模型来展示您遇到的特殊困难。这样您就可以包含真实代码(而不是删减比特)和代表性数据(而不是让我们猜测)。见这里:stackoverflow.com/help/mcve
-
当时真的要计算过去10年吗?您不能在级别上预先计算/汇总值以减少行数吗?
标签: sql oracle plsql oracle11g