Question

I'm trying to get a UNION ALL working with a CTE which I'm using for paging. I need to get all records matching a set of criteria from two tables, then page the results. The first table's CTE looks like this:

;WITH Results_CTE AS (SELECT t1.SomeIntKey1, ROW_NUMBER() OVER (ORDER BY SomeIntKey1) AS RowNum  
 FROM Table1 t1
 LEFT JOIN CalculatedData d ON d.Key = t1.SomeIntKey1
 WHERE Postcode LIKE 'CHX 1XX%' 
 ) SELECT * FROM Results_CTE a INNER JOIN CalclatedData d ON a.SomeIntKey1 = d.Key WHERE RowNum >= 0 AND RowNum <= 10 OPTION(RECOMPILE) 

The second table's paging SQL (which works fine) is:

;WITH Results_CTE AS (SELECT t2.SomeIntKey2, ROW_NUMBER() OVER (ORDER BY SomeIntKey2) AS RowNum  
 FROM Table2 t2
 LEFT JOIN CalculatedData d ON d.Key = t1.SomeIntKey2
 WHERE Postcode LIKE 'CHX 1XX%' 
 ) SELECT * FROM Results_CTE a INNER JOIN CalclatedData d ON a.SomeIntKey2 = d.Key WHERE RowNum >= 0 AND RowNum <= 10 OPTION(RECOMPILE) 

For the combined paged data, I've tried something like:

;WITH Results_CTE AS (SELECT t2.SomeIntKey2, ROW_NUMBER() OVER (ORDER BY SomeIntKey2) AS RowNum  
 FROM Table2 t2
 LEFT JOIN CalculatedData d ON d.Key = t1.SomeIntKey2
 WHERE Postcode LIKE 'CHX 1XX%' 
UNION ALL 
SELECT t1.SomeIntKey1
 FROM Table1 t1
 LEFT JOIN CalculatedData d ON d.Key = t1.SomeIntKey1
 WHERE Postcode LIKE 'CHX 1XX%' 
 ) SELECT * FROM Results_CTE a INNER JOIN CalclatedData d ON a.SomeIntKey2 = d.Key WHERE RowNum >= 0 AND RowNum <= 10 OPTION(RECOMPILE) 

However, this results in an error: All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.

I know UNION ALLs can be confusing at the best of times, especially with joins, but I'm essentially getting a list of INT keys from two tables, then joining them to a third which contains the data I need (keys from both tables will be present in the joined column on the Data table.

Was it helpful?

Solution

You need to make sure that both result sets have the same columns:

WITH Results_CTE AS
(
    SELECT
        t2.SomeIntKey2 as Key,
        ROW_NUMBER() OVER (ORDER BY SomeIntKey2) AS RowNum  
    FROM
        Table2 t2
    LEFT JOIN CalculatedData d
        ON  d.Key = t1.SomeIntKey2
    WHERE Postcode LIKE 'CHX 1XX%' 
    UNION ALL 
    SELECT
        t1.SomeIntKey1 as Key,
        0 as RowNum
    FROM
        Table1 t1
    LEFT JOIN CalculatedData d
        ON  d.Key = t1.SomeIntKey1
    WHERE Postcode LIKE 'CHX 1XX%' 
 )
 SELECT * FROM Results_CTE a INNER JOIN CalclatedData d ON a.SomeIntKey2 = d.Key
 WHERE RowNum >= 0 AND RowNum <= 10 OPTION(RECOMPILE) 

Please note that the second part of the UNION ALL now always returns 0 for the RowNum. If you want to have the RowNum column for the result of the UNION ALL you need another sub query:

WITH Results_CTE AS
(
    SELECT
        s.Key,
        ROW_NUMBER() OVER (ORDER BY s.Key) AS RowNum
    FROM
    (
        SELECT
            t2.SomeIntKey2 as Key,
        FROM
            Table2 t2
            LEFT JOIN CalculatedData d
                ON  d.Key = t1.SomeIntKey2
        WHERE Postcode LIKE 'CHX 1XX%' 
        UNION ALL 
        SELECT
            t1.SomeIntKey1 as Key
        FROM
            Table1 t1
            LEFT JOIN CalculatedData d
                ON  d.Key = t1.SomeIntKey1
        WHERE Postcode LIKE 'CHX 1XX%' 
     )
 )
 SELECT * FROM Results_CTE a INNER JOIN CalclatedData d ON a.SomeIntKey2 = d.Key
 WHERE RowNum >= 0 AND RowNum <= 10 OPTION(RECOMPILE) 

OTHER TIPS

Your second SELECT in the your UNION ALL doesn't return the same number of columns, hence the problem.

Try:

;WITH Results_CTE AS (
  SELECT IntKey, ROW_NUMBER() OVER (ORDER BY IntKey) AS RowNum  
  FROM
  (
     SELECT t2.SomeIntKey2 AS IntKey
     FROM Table2 t2
        LEFT JOIN CalculatedData d ON d.Key = t1.SomeIntKey2
     WHERE Postcode LIKE 'CHX 1XX%' 
     UNION ALL 
     SELECT t1.SomeIntKey1 AS IntKey
     FROM Table1 t1
        LEFT JOIN CalculatedData d ON d.Key = t1.SomeIntKey1
     WHERE Postcode LIKE 'CHX 1XX%' 
  ) t
 ) 
SELECT * FROM Results_CTE a INNER JOIN CalclatedData d ON a.IntKey = d.Key
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top