Избегайте повторяющихся условий в select case и where.

У меня есть таблица TAB1 со следующими столбцами:
USER_ID NUMBER(5),
PHN_NO1 CHAR(20),
< strong>PHN_NO2 CHAR(20)

Мне нужно извлечь записи из TAB1 в другую таблицу TAB2, чтобы все записи с одним из двух или с обоими PHN_NO1 и PHN_NO2 имели длину 10 и начинаться с 5.
Если в записи, скажем, только PHN_NO1 удовлетворяет условию, а PHN_NO2 нет, тогда TAB2.P1 должен быть таким же, как TAB1.PHN_NO1, но TAB2.P2 должен быть NULL.
Если ни один из два удовлетворяют условию, то запись не должна быть вставлена ​​в TAB2

Структура TAB2 будет следующей:
номер USER_ID(5)- содержит ROWID записи, выбранной из TAB1
P1 char(10)- содержит TAB1.PHN_NO1, если он имеет длину 10 и начинается с 5, иначе NULL
P2 char(10) — содержит TAB1.PHN_NO2, если он имеет длину 10 и начинается с 5, иначе NULL

Я мог бы написать приведенный ниже запрос для достижения вышеуказанного, но условия в CASE и WHERE повторяются. Пожалуйста, предложите способ достижения вышеизложенного лучшим способом.


CREATE TABLE TAB2
AS
SELECT
USER_ID,
CASE WHEN
(LENGTH(TRIM(PHN_NO1)) = 10 AND TRIM(PHN_NO1) как '5%')
THEN
CAST(TRIM(PHN_NO1) as CHAR(10))
ELSE
CAST(NULL as CHAR(10))
END AS P1,
CASE (LENGTH(TRIM(PHN_NO2)) = 10 AND TRIM(PHN_NO2) как '5%')
THEN
CAST(TRIM(PHN_NO2) as CHAR(10))
ELSE< br/> CAST(NULL as CHAR(10))
END AS P2
WHERE
(LENGTH(TRIM(PHN_NO1) = 10 AND TRIM(PHN_NO1) as '5%')
ИЛИ
(LENGTH(TRIM(PHN_NO2) = 10 AND TRIM(PHN_NO2) как '5%')


person user194210    schedule 24.08.2012    source источник


Ответы (1)


Что вы можете! Однако вам нужно использовать некоторые условия:

INSERT INTO New_Phone 
        SELECT user_id, phn_no1, phn_no2
        FROM (SELECT user_id,
              CASE WHEN LENGTH(TRIM(phn_no1)) = 10 AND TRIM(phn_no1) like '5%'
                   THEN SUBSTR(phn_no1, 1, 10) ELSE NULL END phn_no1, 
              CASE WHEN LENGTH(TRIM(phn_no2)) = 10 AND TRIM(phn_no2) like '5%'
                   THEN SUBSTR(phn_no2, 1, 10) ELSE NULL END phn_no2
              FROM Old_Phone) Old
        WHERE phn_no1 IS NOT NULL
        OR phn_no2 IS NOT NULL;

(У меня есть работающий SQL Fiddle пример.)

Это должно работать на любой СУБД. Обратите внимание, что из-за ваших данных это вряд ли будет менее производительнее, чем исходное (в котором не использовался бы индекс, учитывая TRIM()). Это также вряд ли будет лучше, учитывая, что большинство основных СУБД могут повторно использовать результаты детерминированных функций для каждой строки.

О, следует отметить, что на международном уровне телефонные номера могут содержать до 15 цифр (минимум 6 цифр внутри страны). Может быть, использовать VARCHAR (а также сэкономить несколько TRIM())? И INTEGER (или BIGINT, может TINYINT) чаще используется для суррогатных id, NUMBER немного странно.

person Clockwork-Muse    schedule 24.08.2012
comment
Спасибо! Это решает цель. Это было просто упрощенное объяснение того, чего я хотел достичь, поэтому длина номера телефона в моем случае не имеет значения. Большое спасибо за ответ :) - person user194210; 26.08.2012