Как разделить столбец на 2, исходя из определенных условий в Oracle SQL? - PullRequest
1 голос
/ 04 февраля 2020

У меня есть таблица данных на 250 тыс., И из этих данных у меня есть 1000 строк с одинаковыми данными в каждой строке столбца, один ссылочный столбец, который отличается.

Я хотел бы сделать следующее. разделить контрольный столбец, если определенные условия выполнены, и если эти условия не выполняются, контрольное значение может остаться без изменений.

Ниже приведены мои операторы создания таблицы и вставки:

CREATE TABLE "BU_TABLE" 
   (   
    "NAME" VARCHAR2(255 BYTE), 
    "TEL_NO" VARCHAR2(255 BYTE), 
    "POST_CODE" VARCHAR2(8 BYTE), 
    "REF_NO" VARCHAR2(255 BYTE)
;

Причина, по которой я установил столбцы Tel_No и Ref_No как Varchar2, заключается в том, что пробелы, как и у чисел, содержат пробелы: a) при вводе b) Tel_No при В данном примере данные не имеют этой проблемы, но по мере добавления дополнительных данных эта проблема может возникнуть в будущем.

Вставьте операторы:

Insert into BU_TABLE (NAME,TEL_NO,POST_CODE,REF_NO) values ('Damian','7900123456','ME1 2BC','12345678 1234567891234');
Insert into BU_TABLE (NAME,TEL_NO,POST_CODE,REF_NO) values ('Graeme','7900789012','ME1 2DE','12 345 5678901234567');
Insert into BU_TABLE (NAME,TEL_NO,POST_CODE,REF_NO) values ('Sarah','7900456789','ME1 2FG','90123456 890123456789');

Теперь, что я хотел бы для BU_TABLE чтобы остаться без изменений с необработанными данными. Я хотел бы создать еще одну таблицу на обороте этой таблицы, чтобы разделить Ref_No, поэтому у меня есть последовательность из 8 чисел, пробел и затем 13 чисел. Везде, где встречается этот шаблон, я хотел бы продублировать строку и дать мне следующее:

Name   | Tel_No     | Post_Code | Ref_No
Damian | 7900123456 | ME1 2BC   | 12345678
Damian | 7900123456 | ME1 2BC   | 1234567891234

Строки, в которых требуемый код не нашел последовательность, строки данных в таблице останутся одинаковыми, поэтому мой финальный стол будет выглядеть так. Это показывает новое разделение данных, в котором 2 ссылочных номера Дамиана были разделены и теперь отображаются как 2 строки, а Грэм и Сара имеют свои исходные ссылочные номера, поскольку их последовательности не соответствуют критериям.

Финальная таблица:

Name   | Tel_No     | Post_Code | Ref_No
Graeme | 7900789012 | ME1 2DE   | 12 345 5678901234567
Sarah  | 7900456789 | ME1 2FG   | 90123456 890123456789
Damian | 7900123456 | ME1 2BC   | 12345678
Damian | 7900123456 | ME1 2BC   | 1234567891234

Надеюсь, мои требования ясны с точки зрения того, что я ищу.

Извинения, поскольку есть еще один пост с тем же вопросом: Как мне скопировать строку и разделить ее столбцов, основанных на определенных критериях в Oracle SQL?

, но вопрос был закрыт, когда меня попросили добавить операторы create и insert, чтобы сделать мои требования более понятными, поэтому я создал новый вопрос.

Ответы [ 3 ]

1 голос
/ 04 февраля 2020

Вы можете сделать это с union all. Ниже я показываю другой подход - использование общей техники отмены из прежних времен (до того, как Oracle ввел оператор unpivot). Это будет более эффективно, чем решения, использующие union all, поскольку для этого требуется только одно полное сканирование таблицы.

Я не показываю создание таблицы; Я показываю оператор select, который можно использовать для заполнения новой таблицы.

select bu.name, bu.tel_no, bu.post_code,
       case when regexp_like(bu.ref_no, '^\d{8} \d{13}$') 
            then
                 case t.c when 1 then substr(bu.ref_no, 1, 8) 
                                 else substr(bu.ref_no, 10)   end
            else bu.ref_no
       end as ref_no
from   bu_table bu join (select 1 as c from dual union all select 2 from dual) t
                   on t.c = 1 or regexp_like(bu.ref_no, '^\d{8} \d{13}$')
;

NAME    TEL_NO      POST_CODE    REF_NO
------  ----------  ---------  -----------------------
Damian  7900123456  ME1 2BC    12345678
Graeme  7900789012  ME1 2DE    12 345 5678901234567
Sarah   7900456789  ME1 2FG    90123456 890123456789
Damian  7900123456  ME1 2BC    1234567891234
0 голосов
/ 04 февраля 2020

Вы можете использовать следующий запрос:

SQL> SELECT NAME, TEL_NO, POST_CODE,
  2          CASE
  3              WHEN CNT = 1 THEN REF_NO
  4              ELSE CASE
  5                  WHEN L = 1 THEN SUBSTR(REF_NO, 1, 8)
  6                  ELSE SUBSTR(REF_NO, 10)
  7              END
  8          END AS REF_NO
  9  FROM
 10      (SELECT T.*,
 11              CASE
 12                  WHEN REGEXP_LIKE ( REF_NO,
 13                                     '^[0-9]{8} [0-9]{13}$' ) THEN 2
 14                  ELSE 1
 15              END AS CNT
 16         FROM BU_TABLE T ) MT
 17      JOIN (SELECT LEVEL AS L
 18              FROM DUAL CONNECT BY LEVEL <= 2
 19      ) ON ( CNT >= L );

NAME       TEL_NO       POST_COD REF_NO
---------- ------------ -------- ------------------------
Damian     7900123456   ME1 2BC  12345678
Graeme     7900789012   ME1 2DE  12 345 5678901234567
Sarah      7900456789   ME1 2FG  90123456 890123456789
Damian     7900123456   ME1 2BC  1234567891234

SQL>

Cheers !!

0 голосов
/ 04 февраля 2020

Вы можете делать что хотите, используя union all:

select bu.Name, bu.Tel_No, bu.Post_Code, bu.Ref_No
from bu
where not regexp_like(ref_no, '^[0-9]{8} [0-9]{13}$')
union all
select bu.Name, bu.Tel_No, bu.Post_Code, substr(bu.Ref_No, 1, 8)
from bu
where regexp_like(ref_no, '^[0-9]{8} [0-9]{13}$')
union all
select bu.Name, bu.Tel_No, bu.Post_Code, substr(bu.Ref_No, -13)
from bu
where regexp_like(ref_no, '^[0-9]{8} [0-9]{13}$');
...