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.

Était-ce utile?

La 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) 

Autres conseils

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top