SAP HANA SQL SUBSTR_REGEXPR匹配聚合

问题描述 投票:0回答:2

我正在使用HANA,并且正在尝试根据以下内容创建新列:

  Regex Example 1: SUBSTR_REGEXPR('([PpSs][Tt][Ss]?\w?\d{2,6})' in "TEXT") as "Location"

我怎样才能得到这个而不仅仅是第一个?是重复这个表达式的字符串聚合吗?每个文本字段中最多有6个匹配项(每行)。

正则表达式示例1当前输出:

Row                    Text                           Location(new column)
 1        msdfmsfmdf PT2222, ST 43434 asdasdas              PT2222

正则表达式示例1所需输出:

Row                    Text                           Location(new column)
 1        msdfmsfmdf PT2222, ST 43434 asdasdas              PT2222, ST43434

我也有不同的格式,所以我需要能够使用该正则表达式的多个变体来捕获所有匹配并将它们作为分隔聚合放入新的“位置”列。这可能吗?

其他变化之一是我需要从这个系列中提取数字:

   "Locations 1, 2, 35 & 5 lkfaskjdlsaf .282 lkfdsklfjlkdsj 002"

到目前为止,我有:

  Regex Example 2: "Locations (\d{1,2}.?){1,5}"

但我知道这不起作用。当我删除“位置”时,它会拾取数字,但也会选择我不想要的.282和002。

正则表达式示例2当前输出:

Row                    Text                           Location(new column)
 1        msdfmsfmdf Locations 3,5,7 & 9" asdasdas         Locations 3

正则表达式示例2所需输出:

Row                    Text                           Location(new column)
 1        msdfmsfmdf Locations 3,5,7 & 9" asdasdas           3,5,7,9 

有时文本字段中的“位置”采用的格式需要示例1的正则表达式,有时它采用的格式需要示例2s正则表达式,因此我需要让正则表达式搜索两种可能的格式。

 Example 3 Regex in Select Statement: 
     Select "Primary Key",
     "Text", 
     STRING_AGG(SUBSTR_REGEXPR('([PpSs][Tt][Ss]?\w?\d{2,6})' OR '(\d{1,2}.?){1,5})' in "Text" ),',') as "Location"
     FROM Table

需要在create column SQL中使用某种OR条件捕获示例1和2位置格式

 Regex Example 3 Current Output:

                   Not working, no output

正则表达式示例3所需输出:

Row                    Text                           Location(new column)
 1        msdfmsfmdf Locations 3,5,7 & 9" asdasdas           3,5,7,9
 2        msdfmsfmdf PT2222, ST 43434 asdasdas            PT2222, ST43434

我可以访问的其他工具是SAS和python。欢迎任何简化过程的替代建议。我已经尝试过Tableau,但同样的问题只返回第一场比赛。聚合它们会使计算变得非常缓慢且非常长。

请帮我解决这个问题。任何帮助深表感谢。

谢谢。

sql regex substring hana
2个回答
0
投票

感谢您添加必要的需求示例。这使得解决问题变得容易得多。

在这种情况下,您的要求是将多个字符串与多个模式匹配,并在输出上应用多个格式化操作。

这不能在SAP HANA中的单个正则表达式中完成。

基本上,SAP HANA SQL允许两种正则表达式操作:

  • 匹配模式并返回一个匹配项
  • 匹配模式并替换此匹配的一个或所有匹配项

这意味着对于这种转换,我们基本上可以尝试删除与模式不匹配的所有内容或循环输入字符串并选择匹配的所有内容。 remove-approach的问题(例如使用SUBSTR_REGEXPR())是匹配模式不能保证不重叠。这意味着我们可以删除流程中其他模式的匹配项。

相反,我会使用第一种方法,并尝试选择所有模式的所有匹配并返回那些。

为此,可以像这样创建标量用户定义函数:

drop function extract_locators;

create function extract_locators(IN input_text NVARCHAR(1000))
returns location_text NVARCHAR(1000)
as 
begin
declare matchers  NVARCHAR(100) ARRAY;
declare part_res NVARCHAR(100) := '';
declare full_res NVARCHAR (2000) := '';
declare occn integer;
declare curr_matcher integer;

-- setting up matchers
    matchers[1] :=  '(PT\s*[[:digit:]]+)|(ST\s*[[:digit:]]+)';  -- matches PTxxxx, pt xxxx , St ... , STxxxx
    matchers[2] := '(?>\s)[1-9][0-9]*'; -- matches 21, 1, 23, 34

    curr_matcher :=0;
    -- loop over all matchers
    while (:curr_matcher < cardinality(:matchers)) do
        curr_matcher := :curr_matcher + 1;
        -- loop over  all occurrences

        occn := 1;
        part_res := '';
        while (:part_res IS NOT NULL) do
            part_res := SUBSTR_REGEXPR(:matchers[:curr_matcher]  
                                        FLAG 'i' 
                                        IN :input_text  
                                        OCCURRENCE :occn);
            if (:part_res IS NOT NULL) then
                occn := :occn + 1;
                full_res := :full_res 
                            || MAP(LENGTH(:full_res), 0, '', ',')
                            || IFNULL(:part_res, '');
            else
                BREAK;
            end if;
        end while; -- occurrences

        -- if current matcher matched, don't apply the others
        if (:full_res !='') then
            BREAK;
        end if;

    end while; -- matchers  

    -- remove spaces
    location_text := replace (:full_res, ' ', '');
end;

将测试数据放在如下表中:

drop table loc_data;
create column table loc_data ("CASE" integer primary key,
                            "INPUT_TEXT" NVARCHAR(2000));
-- PT and ST
insert into loc_data values (1, 'msdfmsfmdf PT2222, ST 43434 asdasdas');
-- Locations
insert into loc_data values (2, 'Locations 1, 2, 35 & 5 lkfaskjdlsaf .282 lkfdsklfjlkdsj 002');

你现在可以简单地运行

select 
    *
    , extract_locators("INPUT_TEXT") as location_text
from 
    loc_data;

要得到

1 | msdfmsfmdf PT2222, ST 43434 asdasdas                        | PT2222,ST43434
2 | Locations 1, 2, 35 & 5 lkfaskjdlsaf .282 lkfdsklfjlkdsj 002 | 1,2,35,5

此方法还允许将匹配规则保存在单独的表中,并使用游标(而不是数组)循环它们。除此之外,它使单个正则表达式保持相当小且相对容易理解,这可能是最大的好处。

运行时性能显然可能是一个问题,因此我可能会尝试保存操作的结果,并仅在数据更改时运行该函数。


0
投票

对于单个输入字符串值,可以使用以下脚本。使用带有Seri​​es_Generate_Integer的SubStr_RegExpr到split string using SQLScript in HANA可以描述以理解series_generate函数的使用

declare pString nvarchar(5000);
pString := 'msdfmsfmdf PT2222, ST 43434 asdasdas';

select
 STRING_AGG(SUBSTR_REGEXPR( '([PpSs][Tt][Ss]?\w?\d{2,6})' IN Replace(pString,' ','') OCCURRENCE NT.Element_Number GROUP 1),',') as "Location"
from
 DUMMY as SplitString,
 SERIES_GENERATE_INTEGER(1, 0, 10 ) as NT; 

输出将返回PT2222,ST43434

© www.soinside.com 2019 - 2024. All rights reserved.