Преобразование цифр, извлеченных при совпадении подстроки, в годы в PostgreSQL 11,0 - PullRequest
1 голос
/ 06 августа 2020

У меня есть следующая таблица в PostgreSQL 11.0

min age      max age
1 Month      12 Months
1 Year       16 Years
1 Day        365 Days
365 Days     369 Days
N/A          N/A
NULL         NULL

Я хотел бы преобразовать значения в год. Я извлекаю строку после di git и проверяю, есть ли это «годы», «месяцы» или «дни», а затем конвертирую di git перед строкой в ​​год.

Я пробовал следовать запрос:

update tbl
set min_age = 
        case 
                when substring(min_age, '^\d+\s(.*)') ~* 'Month'
                then abs(substring(min_age, '^(\d+)\s.*')/12)
                when substring(min_age, '^\d+\s(.*)') ~* 'Months'
                then abs(substring(min_age, '^(\d+)\s.*')/12)
                when substring(min_age, '^\d+\s(.*)') ~* 'Day'
                then abs(substring(min_age, '^(\d+)\s.*')/365)
                when substring(min_age, '^\d+\s(.*)') ~* 'Days'
                then abs(substring(min_age, '^(\d+)\s.*')/365)
                when substring(min_age, '^\d+\s(.*)') ~* 'Year'
                then abs(substring(min_age, '^(\d+)\s.*'))
                when substring(min_age, '^\d+\s(.*)') ~* 'Years'
                then abs(substring(min_age, '^(\d+)\s.*'))
        end ;

update tbl
set max_age = case
                when substring(min_age, '^\d+\s(.*)') ~* 'Month'
                then abs(substring(min_age, '^(\d+)\s.*')/12)
                when substring(min_age, '^\d+\s(.*)') ~* 'Months'
                then abs(substring(min_age, '^(\d+)\s.*')/12)
                when substring(min_age, '^\d+\s(.*)') ~* 'Day'
                then abs(substring(min_age, '^(\d+)\s.*')/365)
                when substring(min_age, '^\d+\s(.*)') ~* 'Days'
                then abs(substring(min_age, '^(\d+)\s.*')/365)
                when substring(min_age, '^\d+\s(.*)') ~* 'Year'
                then abs(substring(min_age, '^(\d+)\s.*'))
                when substring(min_age, '^\d+\s(.*)') ~* 'Years'
                then abs(substring(min_age, '^(\d+)\s.*'))
           end

Ожидаемый результат:

min age       max age
0             1
1             16
0             1
1             1
N/A           N/A
NULL          NULL

Любая помощь приветствуется.

Ответы [ 2 ]

4 голосов
/ 06 августа 2020

Postgres имеет мощные интервальные функции. Я думаю, что cast и justify_interval() могут просто работать здесь:

select
    extract(year from justify_interval(min_age::interval)) min_age,   
    extract(year from justify_interval(max_age::interval)) max_age
from tbl

Демо на DB Fiddle :

min_yr | max_yr
:----- | :-----
0      | 1     
1      | 16    
0      | 1     
1      | 1     
0 голосов
/ 06 августа 2020

Вот как вы можете получить все необходимые вам значения:

select split_part(min_age, " ", 1) as min_age_value, split_part(min_age, " ", 2) as min_age_unit, split_part(max_age, " ", 1) as max_age_value, split_part(max_age, " ", 2) as max_age_unit
from tbl;

Теперь вы можете использовать указанное выше как подстроку и использовать case-when для min_age_unit и max_age_unit во внешнем запросе, оценивая его до 1, 12 или 365 соответственно и умножая его на фактическое значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...