получить целые числа из строки - PullRequest
0 голосов
/ 19 февраля 2019

У меня есть в базе данных такие данные, как это

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

, и проблема заключается в том, чтобы получить значение AVG по следующей формуле псевдо [ summ(all(min_hrv)) + summ(all(max_hrv)) ] / count(all(min_hrv)) + all(max_hrv)), для результата строки примера будет ((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 все еще в строке, результат:

                  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 голосов
/ 19 февраля 2019

Шаблон, который вы ищете, должен соответствовать цифрам после #, полосе цифр и символу /regexp_matches вы можете извлечь часть шаблона только в том случае, если вы заключите эту часть в пару скобок.

Решение -

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

Обратите внимание, что g означает global, что означает, что будут возвращены все найденные в строке вхождения.

Детали шаблона

  • \d+ - 1 или более (+) цифр
  • / - / char
  • (\d+) - Группа захвата 1: 1 или более цифр

См. Демонстрационный пример regex .

Вы можете извлечь конкретные биты из ваших данных, если вы используете одну пару скобок в разных частях '(\d+)/(\d+)#(\d+)/(\d+)' regex.Чтобы извлечь min_hr, вы должны использовать '(\d+)/\d+#\d+/\d+'.

0 голосов
/ 19 февраля 2019

Использование 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...