SELECT /*+first_rows */ PPS_ID,TOTAL_WEIGHT from
(SELECT PPS_ID,TOTAL_WEIGHT ,row_number() over (order by total_weight desc) row_num
FROM (SELECT pps_id,round((((60 * name_pct_match / 100) + prs_weight + year_weight + dt_weight +
case
when mother_name_pct_match = -1
then
0
else
(10 * mother_name_pct_match / 100)
end)/decode(mother_name_pct_match,-1,(total_attrib_weight - mother_weight),total_attrib_weight)) * 100) total_weight
FROM (SELECT pps_id,
round(func_compare_name('MUHAMMAD YASIN MUHAMMAD ASHRAF',upper(name_en),' ',60)) name_pct_match,
decode(prs_nationality_id, 271, 15, 0) prs_weight,
case
when upper(mother_name_en) in ('MR','MRS','MISS','NISA','M','X')
then -1
else
round(func_compare_name(upper('.'), upper(mother_name_en), ' ',60))
end mother_name_pct_match, 10 mother_weight,
100 total_attrib_weight,
case when to_number(to_char(birth_date, 'yyyy')) = 2007 then 5 else 0 end year_weight,
case when to_char(to_date('01/01/2007','DD-MM-RRRR'), 'dd') = to_char(birth_date, 'dd')
and to_char(to_date('01/01/07','DD-MM-RRRR'), 'mm') = to_char(birth_date, 'mm') then 10
when to_date('01/01/2007','DD-MM-RRRR') between birth_date-6 and birth_date+6 then 8
when to_date('01/01/2007','DD-MM-RRRR') between birth_date-28 and birth_date+28 then 5
when to_date('01/01/2007','DD-MM-RRRR') between birth_date-90 and birth_date+90 then 3
else 0
end dt_weight
FROM INDIV_PROF_sub_test123
WHERE birth_date = '01/01/2007'
AND IS_ACTIVE = 1
AND gender_id = 1
AND round(func_compare_name('MUHAMMAD YASIN MUHAMMAD ASHRAF',upper(name_en),' ',60)) > 20
)
)
WHERE TOTAL_WEIGHT >= 70
)
where row_num <= 10
CREATE OR REPLACE FUNCTION VISION_APP.func_compare_name(p_name_str IN VARCHAR2,
p_str IN VARCHAR2,
p_delim IN VARCHAR2,
p_relev_thresh IN NUMBER)
RETURN NUMBER DETERMINISTIC AS
l_str LONG;
l_n NUMBER;
TYPE mytabletype IS TABLE OF VARCHAR2(255);
l_name_data mytabletype := mytabletype();
l_data mytabletype := mytabletype();
v_name_cnt NUMBER := 0;
v_pct_per_name NUMBER := 0;
v_pct_match NUMBER := 0;
v_flag NUMBER;
v_jaro_pct NUMBER := 0;
v_highest_jaro_pct NUMBER := 0;
v_match_exact NUMBER := 0;
v_match_exact_res NUMBER := 0;
BEGIN
l_str := p_name_str || p_delim;
LOOP
l_n := instr(l_str, p_delim);
EXIT WHEN(nvl(l_n, 0) = 0);
-- condition to check if only space
IF l_n <> 1 THEN
l_name_data.extend;
l_name_data(l_name_data.count) := ltrim(rtrim(substr(l_str,
1,
l_n - 1)));
v_name_cnt := v_name_cnt + 1;
END IF;
l_str := substr(l_str, l_n + length(p_delim));
END LOOP;
v_pct_per_name := 100 / v_name_cnt;
l_str := p_str || p_delim;
LOOP
l_n := instr(l_str, p_delim);
EXIT WHEN(nvl(l_n, 0) = 0);
l_data.extend;
l_data(l_data.count) := ltrim(rtrim(substr(l_str, 1, l_n - 1)));
l_str := substr(l_str, l_n + length(p_delim));
END LOOP;
FOR nme IN 1 .. l_name_data.count LOOP
v_flag := 0;
v_highest_jaro_pct := 0;
FOR i IN 1 .. l_data.count LOOP
v_jaro_pct := utl_match.jaro_winkler_similarity(l_name_data(nme),
l_data(i));
IF soundex(l_name_data(nme)) = soundex(l_data(i)) AND
v_jaro_pct >= p_relev_thresh THEN
IF v_jaro_pct > v_highest_jaro_pct THEN
v_highest_jaro_pct := v_jaro_pct;
END IF;
END IF;
END LOOP;
v_pct_match := v_pct_match +
(v_pct_per_name * v_highest_jaro_pct / 100);
END LOOP;
SELECT utl_match.edit_distance_similarity(p_name_str, p_str)
INTO v_match_exact
FROM dual;
if (trunc(v_match_exact) =100 ) then
return trunc(v_pct_match, 2);
else
if( v_match_exact <> 0) then
v_match_exact_res := (5 / v_match_exact) * 100;
v_pct_match := v_pct_match - v_match_exact_res;
end if;
if v_pct_match >20 then
RETURN trunc(v_pct_match, 2);
end if;
end if;
END;
此查询从INDIV_PROF_sub_test123表中获取结果,该表具有3500万的数据并已分区。
我在查询func_compare_name中找到了有问题的区域,我们正在使用它具有名称相似性检查功能
添加解释计划:
Plan
SELECT STATEMENT HINT: FIRST_ROWS
Cost: 262
Bytes: 4,056
Cardinality: 104 4
VIEW VC_CLONE.
Cost: 262
Bytes: 4,056
Cardinality: 104 3
WINDOW SORT PUSHED RANK
Cost: 262
Bytes: 5,512
Cardinality: 104 2
TABLE ACCESS BY GLOBAL INDEX ROWID TABLE VC_CLONE.INDIV_PROF_ONE_MONTH_1
Cost: 261
Bytes: 5,512
Cardinality: 104
Partition #: 3
Partitions accessed #1672 1
INDEX RANGE SCAN INDEX VC_CLONE.IDX_BIRTH_DT_INVID
Cost: 4
Cardinality: 1 –