存储过程最大模式匹配

时间:2015-10-21 05:16:05

标签: sql oracle stored-procedures top-n

这是我在Oracle中的存储过程:

 CREATE OR REPLACE PROCEDURE execute_cproc (  callnum IN VARCHAR2
                                            , RESULT  OUT VARCHAR2)
 AS
   vara_val NUMBER;
   varb_val NUMBER;
 BEGIN
   SELECT a_val, b_val
     INTO vara_val, varb_val
     FROM data_table
    WHERE callnum LIKE numberpattern || '%';
 END;

如果CALLNUM是03354123,那么我得到2个结果:

  1. 03354123 like 033%

  2. 03354123 like 03354%

  3. 两者都是真的,所以我得到2个结果。

    如何让程序找到最长的匹配,即03354123 like 03354%

    表:

    表名:DATA_TABLE

    列:

    NumberPattern (varchar2) : 033, 03354
    
    a_val ( integer ) : 1, 2
    
    b_val ( integer ) : 1, 2
    

3 个答案:

答案 0 :(得分:2)

您必须重新构建查询。如果您想获得最佳或最大模式,请执行以下操作:

  select  a_val, b_val 
  into vara_val, varb_val 
  from 
      (select NumberPattern , 
              a_val,
               b_val,
               rank() over(order by length(NumberPattern) desc) ranking 
         from DATA_TABLE  
         where CALLNUM  like NumberPattern  || '%' ) 
         where ranking = 1

这会将变量vara_val和varb_val分别设置为值2,2。或者,如果您也想获得该模式,只需声明另一个将保存该值的变量,然后将您的查询编辑为:

    select  NumberPattern ,a_val, b_val 
    into yournew_variable,vara_val, varb_val 
    from 
      (select NumberPattern , 
              a_val,
               b_val,
               rank() over(order by length(NumberPattern) desc) ranking 
         from DATA_TABLE  
         where CALLNUM  like NumberPattern  || '%' ) 
         where ranking = 1

这里有一个简短的解释:我创建了一个子查询,它由NumberPattern,a_val,b_val和NumberPattern的等级根据其长度组成。这将仅对您提供的CALLNUM参数上存在的模式进行排名。例如,您获得了模式12345,1234,789并且您将123456789传递给您的CALLNUM参数,它将仅对模式12345和1234进行排名,因为您的CALLNUM以12345和1234开始,而不是789.一旦排名,我选择了来自该子查询的NumberPattern,a_val和b_val,其中排名为1

答案 1 :(得分:0)

您建议的解决方案是否提供了答案?

如果您的数据包含以下内容怎么办?

03354121 03354122 03354123

这些都将匹配03354%。哪一个最好?

也许没有答案。

一个“修复”是按降序对数据进行排序并选择第一个结果。

答案 2 :(得分:-1)

你能做到这一点(对不起,我没有要测试的Oracle DB):

select a_val, b_val into vara_val, varb_val
  from (
    select 
        a_val, b_val, NumberPattern, row_number() as r
    from 
        DATA_TABLE 
    where 
        CALLNUM LIKE NumberPattern || '%'
    order by NumberPattern  DESC)
where r = 1; 

由于我无法测试,您可能需要调整语法。