Remove the first two characters in a column value if they meet a certain condition

  • I have a column of data in a table that I need to update and remove the first 2 characters if they are 'NA'

    for example:

    NA11345 needs to be 11345

    NA458267 needs to be 458267

    11587 needs to stay 11587

    So basically anything with a NA in the front of the string, (NA) needs to be removed.

    What script can be developed to do this?

    Thanks

  • Please check this...

    update <table name> set name = SUBSTRING (name,3,len(<column name>)) where SUBSTRING(<column name>,1,2)='NA'

  • UPDATE #TEST_TABLE

    SET COLS = SUBSTRING(COLS,3,LEN(COLS)-2)

    WHERE LEFT(COLS,2) = 'NA'

  • worked like a charm....thanks!

  • eklavu (12/20/2012)


    UPDATE #TEST_TABLE

    SET COLS = SUBSTRING(COLS,3,LEN(COLS)-2)

    WHERE LEFT(COLS,2) = 'NA'

    Possibly not relevant here, but if the 'COLS' column is indexed, a better option would be

    where cols like 'NA%'

    As this will make use of the index, whereas the LEFT function is non-SARGable and will not.

    The absence of evidence is not evidence of absence
    - Martin Rees
    The absence of consumable DDL, sample data and desired results is, however, evidence of the absence of my response
    - Phil Parkin

  • talking of being SARGable, i was reading this article:

    http://en.wikipedia.org/wiki/Sargable

    and didn't quite understand this line

    The typical thing that will make a sql query non-sargable is to include a function in left part of a condition of a Where clause.

    one of the examples given was:

    Non-Sargable: Select ... WHERE DateDiff(mm,Date,GetDate()) >= 20

    does that mean that if it was written like so:

    Select ... WHERE 20 < DateDiff(mm,Date,GetDate())

    that it would be Sargable, as the function is now on the Right hand side of a condition in a where clause?

  • davidandrews13 (12/21/2012)


    talking of being SARGable, i was reading this article:

    http://en.wikipedia.org/wiki/Sargable

    and didn't quite understand this line

    The typical thing that will make a sql query non-sargable is to include a function in left part of a condition of a Where clause.

    one of the examples given was:

    Non-Sargable: Select ... WHERE DateDiff(mm,Date,GetDate()) >= 20

    does that mean that if it was written like so:

    Select ... WHERE 20 < DateDiff(mm,Date,GetDate())

    that it would be Sargable, as the function is now on the Right hand side of a condition in a where clause?

    No. A general rule (although not always true) is that if you wrap the column you are searching in a function then it is not SARGABLE, instead you need to wrap your search argument in the function.

    Try this example: -

    --Standard TestEnvironment of 1,000,000 rows of random-ish data

    IF object_id('tempdb..#testEnvironment') IS NOT NULL

    BEGIN

    DROP TABLE #testEnvironment;

    END;

    --1,000,000 Random rows of data

    SELECT TOP 1000000 IDENTITY(INT,1,1) AS ID,

    RAND(CHECKSUM(NEWID())) * 30000 /*(Number of days in range)*/ + CAST('1945' AS DATETIME) /*(Start date, e.g. '1945-01-01 00:00:00*/ AS randomDateTime,

    DATEADD(DAY,((ABS(CHECKSUM(NEWID())) % 30000 /*(Number of days in range)*/) + 1),CAST('1945' AS DATE) /*(Start date, e.g. '1945-01-01*/) AS randomDate,

    ABS(CHECKSUM(NEWID())) AS randomBigInt,

    (ABS(CHECKSUM(NEWID())) % 100) + 1 AS randomSmallInt,

    RAND(CHECKSUM(NEWID())) * 100 AS randomSmallDec,

    RAND(CHECKSUM(NEWID())) AS randomTinyDec,

    RAND(CHECKSUM(NEWID())) * 100000 AS randomBigDec,

    CONVERT(VARCHAR(6),CONVERT(MONEY,RAND(CHECKSUM(NEWID())) * 100),0) AS randomMoney

    INTO #testEnvironment

    FROM master.dbo.syscolumns sc1, master.dbo.syscolumns sc2, master.dbo.syscolumns sc3;

    CREATE CLUSTERED INDEX cl_testEnvironment_ID ON #testEnvironment(ID ASC);

    CREATE NONCLUSTERED INDEX nc_testEnvironment_randomDate ON #testEnvironment(randomDate ASC);

    So, we have 1,000,000 rows of sample data.

    Let's take a look at your queries: -

    DECLARE @TODAY DATE = GETDATE();

    -- NON-SARGABLE

    SELECT COUNT(*)

    FROM #testEnvironment

    WHERE DateDiff(mm,randomDate,@TODAY) >= 20;

    -- NON-SARGABLE

    SELECT COUNT(*)

    FROM #testEnvironment

    WHERE 20 <= DateDiff(mm,randomDate,@TODAY);

    Both perform an index scan on the "nc_testEnvironment_randomDate" index.

    I would re-write that as something like this: -

    -- SARGABLE

    SELECT COUNT(*)

    FROM #testEnvironment

    WHERE randomDate < DATEADD(mm,-20,DATEADD(MONTH, DATEDIFF(MONTH, 0, @TODAY)+1, 0));

    Which is now able to perform an index seek on the "nc_testEnvironment_randomDate" index.


    Forever trying to learn
    My blog - http://www.cadavre.co.uk/
    For better, quicker answers on T-SQL questions, click on the following...http://www.sqlservercentral.com/articles/Best+Practices/61537/
    For better, quicker answers on SQL Server performance related questions, click on the following...http://www.sqlservercentral.com/articles/SQLServerCentral/66909/

  • A general rule (although not always true) is that if you wrap the column you are searching in a function then it is not SARGABLE, instead you need to wrap your search argument in the function.

    i see. that makes so much sense, i actually feel like i understand it now! cheers 😎

  • Phil Parkin (12/21/2012)


    eklavu (12/20/2012)


    UPDATE #TEST_TABLE

    SET COLS = SUBSTRING(COLS,3,LEN(COLS)-2)

    WHERE LEFT(COLS,2) = 'NA'

    Possibly not relevant here, but if the 'COLS' column is indexed, a better option would be

    where cols like 'NA%'

    As this will make use of the index, whereas the LEFT function is non-SARGable and will not.

    I was so surprised by this that I decided to do a test.

    CREATE TABLE #john (JID int IDENTITY(1,1), testcol char(36));

    -- Insert over a million random rows

    WITH A1(N) AS (SELECT 0 UNION SELECT 1)

    , A2 AS (SELECT a.N FROM A1 a CROSS JOIN A1 b)

    , A3 AS (SELECT a.N FROM A2 a CROSS JOIN A2 b)

    , A4 AS (SELECT a.N FROM A3 a CROSS JOIN A3 b)

    , A5 AS (SELECT a.N FROM A4 a CROSS JOIN A4 b)

    , A6 AS (SELECT a.N FROM A5 a CROSS JOIN A3 b)

    INSERT INTO #John

    SELECT CAST(NEWID() AS char(36))

    FROM A6

    -- Create indexes

    ALTER TABLE #john ADD CONSTRAINT PK_john_JID

    PRIMARY KEY CLUSTERED (JID)

    CREATE NONCLUSTERED INDEX IX_john_testcol

    ON #john(testcol)

    -- Sargable

    SELECT testcol FROM #john WHERE testcol LIKE 'AB%'

    -- Not sargable

    SELECT testcol FROM #john WHERE LEFT(testcol,2) = 'AB'

    And it's true - the first SELECT used an index seek, the second an index scan. I'd have thought that the query optimizer would have been smart enough to realise that an index could still be used for LEFT.

    John

  • DECLARE @tbl TABLE

    (

    ID INT IDENTITY(1,1),

    SomeData VARCHAR(100)

    )

    INSERT INTO @tbl SELECT 'NA11345'

    INSERT INTO @tbl SELECT 'NA113456'

    INSERT INTO @tbl SELECT 'RA11345'

    UPDATE @tbl SET SomeData = SUBSTRING(SomeData,CHARINDEX('NA',SomeData)+2,LEN(SomeData))

    WHERE CHARINDEX('NA',SomeData) = 1

    select * from @tbl

    Regards,
    Mitesh OSwal
    +918698619998

  • Mitesh Oswal (12/21/2012)


    DECLARE @tbl TABLE

    (

    ID INT IDENTITY(1,1),

    SomeData VARCHAR(100)

    )

    INSERT INTO @tbl SELECT 'NA11345'

    INSERT INTO @tbl SELECT 'NA113456'

    INSERT INTO @tbl SELECT 'RA11345'

    UPDATE @tbl SET SomeData = SUBSTRING(SomeData,CHARINDEX('NA',SomeData)+2,LEN(SomeData))

    WHERE CHARINDEX('NA',SomeData) = 1

    select * from @tbl

    I'm a bit surprised that you posted this after the preceding discussion on index usage. Also, why bother with all that SUBSTRING nonsense when you already know that all you want to do is replace the first two characters?

    Instead of

    SomeData = SUBSTRING(SomeData,CHARINDEX('NA',SomeData)+2,LEN(SomeData))

    Use

    SomeData = STUFF(SomeData,1,2,'')

    The absence of evidence is not evidence of absence
    - Martin Rees
    The absence of consumable DDL, sample data and desired results is, however, evidence of the absence of my response
    - Phil Parkin

  • Nice. Now I'm REALLY learning SQL.

    Sometimes reading is not enough to learn.

    You need to interact or post something so that someone can give comments and give a better option.

    Thanks a lot!

Viewing 12 posts - 1 through 11 (of 11 total)

You must be logged in to reply to this topic. Login to reply