Отдельные номера телефонов от строки в ячейке - случайный порядок - PullRequest
0 голосов
/ 08 января 2019

У меня есть набор данных, который содержит номер телефона и день рождения, а также другие данные.

{1997-06-28,07742367858}<br>
{07791100873,1996-07-14}<br>
{30/01/1997,07974335488}<br>
{1997-04-04,07701003703}<br>
{1996-03-11,07480227283}<br>
{1998-06-20,07713817233}<br>
{1996-09-13,07435148920}<br>
{"21 03 2000",07548542539,1st}<br>
{1996-03-09,07539248008}<br>
{07484642432,1996-03-01}<br>

Я пытаюсь извлечь из этого номер телефона, но не знаю, как его получить, если данные не всегда совпадают.

Я ожидаю, что один столбец вернет номер телефона, следующий - день рождения, а другой - любое произвольное значение в 3-м слоте столбца.

1 Ответ

0 голосов
/ 08 января 2019

Вы можете попытаться отсортировать части каждой строки по количеству цифр, которые они содержат. Это можно сделать с помощью выражения:

select length(regexp_replace('1997-06-28', '\D', '', 'g'))

 length 
--------
      8
(1 row)

Запрос удаляет фигурные скобки из строк, разделяет их запятыми, сортирует элементы по количеству цифр и объединяет обратно в массивы:

with my_data(str) as (
values
    ('{1997-06-28,07742367858}'),
    ('{07791100873,1996-07-14}'),
    ('{30/01/1997,07974335488}'),
    ('{1997-04-04,07701003703}'),
    ('{1996-03-11,07480227283}'),
    ('{1998-06-20,07713817233}'),
    ('{1996-09-13,07435148920}'),
    ('{"21 03 2000",07548542539,1st}'),
    ('{1996-03-09,07539248008}'),
    ('{07484642432,1996-03-01}')
)

select id, array_agg(elem order by length(regexp_replace(elem, '\D', '', 'g')) desc)
from (
    select id, trim(unnest(string_to_array(str, ',')), '"') as elem
    from (
        select trim(str, '{}') as str, row_number() over () as id
        from my_data
        ) s
    ) s
group by id

Результат:

 id |           array_agg            
----+--------------------------------
  1 | {07742367858,1997-06-28}
  2 | {07791100873,1996-07-14}
  3 | {07974335488,30/01/1997}
  4 | {07701003703,1997-04-04}
  5 | {07480227283,1996-03-11}
  6 | {07713817233,1998-06-20}
  7 | {07435148920,1996-09-13}
  8 | {07548542539,"21 03 2000",1st}
  9 | {07539248008,1996-03-09}
 10 | {07484642432,1996-03-01}
(10 rows)   

См. Также этот ответ Ищете решение, чтобы поменять местами формат даты с DMY на YMD , если вы хотите нормализовать даты. Вам следует изменить функцию:

create or replace function iso_date(text)
returns date language sql immutable as $$
    select case
        when $1 like '__/__/____' then to_date($1, 'DD/MM/YYYY')
        when $1 like '____/__/__' then to_date($1, 'YYYY/MM/DD')
        when $1 like '____-__-__' then to_date($1, 'YYYY-MM-DD')
        when trim($1, '"') like '__ __ ____' then to_date(trim($1, '"'), 'DD MM YYYY')
    end
$$;

и используйте его:

select id, a[1] as phone, iso_date(a[2]) as birthday, a[3] as comment
from (
    select id, array_agg(elem order by length(regexp_replace(elem, '\D', '', 'g')) desc) as a
    from (
        select id, trim(unnest(string_to_array(str, ',')), '"') as elem
        from (
            select trim(str, '{}') as str, row_number() over () as id
            from my_data
            ) s
        ) s
    group by id
    ) s

 id |    phone    |  birthday  | comment 
----+-------------+------------+---------
  1 | 07742367858 | 1997-06-28 | 
  2 | 07791100873 | 1996-07-14 | 
  3 | 07974335488 | 1997-01-30 | 
  4 | 07701003703 | 1997-04-04 | 
  5 | 07480227283 | 1996-03-11 | 
  6 | 07713817233 | 1998-06-20 | 
  7 | 07435148920 | 1996-09-13 | 
  8 | 07548542539 | 2000-03-21 | 1st
  9 | 07539248008 | 1996-03-09 | 
 10 | 07484642432 | 1996-03-01 | 
(10 rows)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...