从字符串中获取整数

时间:2019-02-19 08:46:47

标签: regex string postgresql parsing

我在数据库中有这样的数据

61/10#61/12,0/12,10/16,0/21,0/12#61/33,0/28#0/34,0/23#0/28

10/16(无#)这样的部分无效的情况下,不应用于计算,

但其他所有格式都为下一个格式min_hr + "/" + min_hrv + "#" + max_hr + "/" + max_hrv

问题是下一个psevdo公式[ summ(all(min_hrv)) + summ(all(max_hrv)) ] / count(all(min_hrv)) + all(max_hrv))获取AVG值,因为轴字符串结果将是((10 + 12 + 28 + 23) + (12 + 33 + 34 + 28))/8) == 22

我尝试的是:

SELECT regexp_replace(
    '61/10#61/12,0/12,10/16,0/21,0/12#61/33,0/28#0/34,0/23#0/28',
    ',\d+/\d+,', ',',
    'g'
);

要删除无效数据,但10/16仍在strin中,结果是:

                  regexp_replace                  
--------------------------------------------------
 61/10#61/12,10/16,0/12#61/33,0/28#0/34,0/23#0/28

如果要很好地清理字符串,我的计划将以这种方式拆分为数组,对于max(不是完整的解决方案,具有空字符串),对于min则没有解决方案:

SELECT 
    regexp_split_to_array(
        regexp_replace(
            '61/10#61/12,0/12,0/12#61/33,0/28#0/34,0/23#0/28',
            ',\d+/\d+,', ',',
            'g'
        )
        ,',?\d+/\d+#\d+/'
    );

结果是:

 regexp_split_to_array 
-----------------------
 {"",12,33,34,28}

然后计算数据,如下所示:

SELECT ((
    SELECT sum(tmin.unnest)
    FROM
        (SELECT unnest('{10,12,28,23}'::int[])) as tmin
    ) 
    + 
    (
    SELECT sum(tmax.unnest)
    FROM
        (SELECT unnest('{12,33,34,28}'::int[])) as tmax
    ))
    /
    (SELECT array_length('{12,33,34,28}'::int[], 1) * 2)

也许有人知道这种问题更简单正确的方法吗?

2 个答案:

答案 0 :(得分:2)

使用regexp_matches()

select (regexp_matches(
    '61/10#61/12,0/12,0/12#61/33,0/28#0/34,0/23#0/28', 
    '\d+#\d+/(\d+)', 
    'g'))[1]

 regexp_matches 
----------------
 12
 33
 34
 28
(4 rows)    

整个计算可能像这样:

with my_data(str) as (
values
    ('61/10#61/12,0/12,10/16,0/21,0/12#61/33,0/28#0/34,0/23#0/28')
),
min_max as (
    select 
        (regexp_matches(str, '(\d+)#\d+', 'g'))[1] as min_hrv,
        (regexp_matches(str, '\d+#\d+/(\d+)', 'g'))[1] as max_hrv
    from my_data
)

select avg(min_hrv::int+ max_hrv::int) / 2 as result
from min_max;

       result        
---------------------
 22.5000000000000000
(1 row)

答案 1 :(得分:1)

您要查找的模式应该与#之后的数字,一连串的数字和一个/字符相同。使用regexp_matches,仅当您将模式的 part 包装在一对圆括号中时,才可以提取该部分。

解决方案是

regexp_matches(your_col, '#\d+/(\d+)', 'g')

请注意,g代表global,这意味着将返回在字符串中找到的所有匹配项。

模式详细信息

  • \d+-1个或更多(+)位数字
  • /-一个/字符
  • (\d+)-捕获第1组:1个或更多数字

请参见regex demo

如果在'(\d+)/(\d+)#(\d+)/(\d+)'正则表达式的不同部分中使用一对括号,则可以从数据中提取特定位。要提取min_hr,请使用'(\d+)/\d+#\d+/\d+'