【问题标题】:Stored Procedure Maximum Pattern Match存储过程最大模式匹配
【发布时间】:2016-01-19 23:40:13
【问题描述】:

这是我在 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%

两者都是正确的,所以我得到 2 个结果。

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

表:

表名:DATA_TABLE

列:

NumberPattern (varchar2) : 033, 03354

a_val ( integer ) : 1, 2

b_val ( integer ) : 1, 2

【问题讨论】:

  • 请帮忙。如果问题不清楚或有任何疑问,请告诉我
  • 什么是'NumberPattern'? 'CALLNUM' 是参数还是来自 'DATA_TABLE' 的列?
  • 问题中添加的表格。 NumberPattern 是表中的列名,过程中输入了 CALLNUM。
  • 在oracle中没有太多的exp,但是你可以像这样使用row_number()..select a_val, vara_val,varb_val from (select a_val, b_val into vara_val, varb_val from DATA_TABLE where CALLNUM LIKE NumberPattern || '%') Z 限定 row_number over (partition by varb_val order by varb_val desc)=1;
  • @anwaar_hell :我希望最大匹配模式应该返回。示例 03354123 喜欢 03354%,而 03354123 喜欢 033%。因为 03354% 更匹配 03354123 而不是 033%。

标签: sql oracle stored-procedures top-n


【解决方案1】:

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

如果您的数据包含:

03354121 03354122 03354123

这些都将匹配 03354%。那么哪个最好呢?

也许没有答案。

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

【讨论】:

  • 是的。在这种情况下,它将全部返回。但是如果数据包含 033541, 033, 03 那么它必须只匹配 1 即 033541 (最大模式匹配)。你能帮忙吗?
  • 答案在我的回复中。按降序排序并选择第一个结果。另见 Turophile 的回答。
【解决方案2】:

你能做到吗(抱歉,我没有可供测试的 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; 

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

【讨论】:

  • row_number() over (order by price) r 是什么?没听懂。
  • 按价格排序?您是指按数字模式排序? =)
【解决方案3】:

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

  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 开始。一旦排名,我选择了排名为 1 的子查询中的 NumberPattern、a_val 和 b_val

【讨论】:

  • RANK() 将在最大长度相同时返回多行。 OP 没有说他们想在这种情况下发生什么。
  • @APC :当有最大长度的平局时,我将不得不检查我的业务案例。
  • @Vance :您提供的查询目前对我有用。给我最好的情况。你能解释一下这个查询吗?
  • 但即使在排名方面的最大长度相同,但模式也会有所不同。例如,模式 12345 和 12344 具有相同的长度但彼此不同。假设他的表中的模式是独一无二的,我相信这个查询会很好,先生@APC
  • 我看到了你关于 rank() 的其他帖子,所以这里有一些额外的信息 :) 行:rank() over(order by length(NumberPattern) desc) 将按 NumberPattern 的长度降序排列,这样长度最长的模式将始终是排名第一。rank () 对我的查询也有很大帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 2012-04-01
  • 1970-01-01
相关资源
最近更新 更多