Home Forums SQL Server 2008 T-SQL (SS2K8) Remove the first two characters in a column value if they meet a certain condition RE: Remove the first two characters in a column value if they meet a certain condition

  • 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/