简体   繁体   中英

Avoiding repetitive conditions in the select case and where clause

I have a table say TAB1 with the following columns -
USER_ID NUMBER(5),
PHN_NO1 CHAR(20),
PHN_NO2 CHAR(20)

I have to fetch records from TAB1 into another table TAB2 such that all records with either one of the two or both PHN_NO1 and PHN_NO2 are of length 10 and begin with 5.
If in a record,say only PHN_NO1 satisfies the condition and PHN_NO2 does not then, TAB2.P1 should be same as TAB1.PHN_NO1 but TAB2.P2 should be NULL.
If neither of the two satisfy the condition, then the record should not be inserted into TAB2

Structure of TAB2 would be as
USER_ID number(5) - holding the ROWID of the record selected from TAB1
P1 char(10) - holding TAB1.PHN_NO1 if it is of length 10 and begins with 5, otherwise NULL
P2 char(10) - holding TAB1.PHN_NO2 if it is of length 10 and beigns with 5, otherwise NULL

I could write the below query to achieve the above, but the conditions in the CASE and WHERE are repetitive. Please suggest a way to achieve the above in a better way.


CREATE TABLE TAB2
AS
SELECT
USER_ID,
CASE WHEN
(LENGTH(TRIM(PHN_NO1)) = 10 AND TRIM(PHN_NO1) like '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) like '5%')
THEN
CAST(TRIM(PHN_NO2) as CHAR(10))
ELSE
CAST(NULL as CHAR(10))
END AS P2
WHERE
(LENGTH(TRIM(PHN_NO1) = 10 AND TRIM(PHN_NO1) like '5%')
OR
(LENGTH(TRIM(PHN_NO2) = 10 AND TRIM(PHN_NO2) like '5%')

Sure you can! You do have to use some conditions though:

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;

(I have a working SQL Fiddle example .)

This should work on any RDBMS. Note that, because of your data, this isn't likely to be less performant than your original (which would not have used an index, given the TRIM() ). It's also not likely to be better , given that most major RDBMSs are able to re-use the results of deterministic functions per-row.

Oh, it should be noted that, internationally, phone numbers can be up to 15 digits in length (with a minimum in-country of 6 or less). Maybe use VARCHAR (and save yourself some TRIM() s, too)? And INTEGER (or BIGINT , maybe TINYINT ) is more often used for surrogate ids, NUMBER is a little strange.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM