Search code examples
sqlsql-serverjoincross-jointempdb

SQL cross join on temp table slow results


Have added the following code to my SQL query: (Note cut down version)

DECLARE @rowType AS TABLE (
    rowTypeLabel NVARCHAR (20));

INSERT  INTO @rowType
VALUES ('Cumulative');

INSERT  INTO @rowType
VALUES ('Non-Cumulative');

--select * from @rowType


SELECT ID,Name,StartDate,
       EndDate,
       rowTypeLabel AS Period
FROM   dbo.sicky CROSS JOIN @rowType
WHERE  (rowTypeLabel = 'Cumulative'
        OR (rowTypeLabel = 'Non-Cumulative'
            AND (EndDate IS NULL
                 OR EndDate BETWEEN CAST (DateAdd(Day, 1 - Day(getDate()), getdate()) AS DATE) AND CAST (DateAdd(month, 1, DateAdd(Day, -Day(getDate()), getdate())) AS DATE))));

Run time has gone from around 10 minutes to around 1 hour, does anyone have any suggestions as to why this may be, the results without this cross join were around 46,000 and after brings back an additional 231 rows (anything that is classed as 'non-cumulative' as per query.


Solution

  • I'm guessing that this is a much simplified example? So I can't give you specifics, but the simple answer is that the cumulative part of the query is doing a lot more work than the non cumulative part.

    Try these two for comparison...

    SELECT ID,Name,StartDate,
           EndDate,
           rowTypeLabel AS Period
    FROM   dbo.sicky
    

    And...

    SELECT ID,Name,StartDate,
           EndDate,
           rowTypeLabel AS Period
    FROM   dbo.sicky
    WHERE  EndDate IS NULL
           OR EndDate BETWEEN CAST (DateAdd(Day, 1 - Day(getDate()), getdate()) AS DATE) AND CAST (DateAdd(month, 1, DateAdd(Day, -Day(getDate()), getdate())) AS DATE))));
    

    The latter, I would expect, will take a lot longer.


    Also, OR conditions to merge multiple pieces of business logic can be quite hard for the optimiser. This means that the following structure may be more efficient...

    SELECT * FROM <non cumulative query>
    UNION ALL
    SELECT * FROM <cumulative query>