Union tout en CTE
-
13-11-2019 - |
Question
J'essaie d'obtenir un syndicat en travaillant avec un CTE que j'utilise pour la pagination. J'ai besoin d'obtenir tous les enregistrements correspondant à un ensemble de critères à partir de deux tables, puis à la mise en œuvre des résultats. Le CTE du premier tableau ressemble à ceci:
;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)
Le SQL de pagination du deuxième tableau (qui fonctionne bien) est:
;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)
Pour les données paginées combinées, j'ai essayé quelque chose comme:
;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)
Cependant, cela entraîne une erreur:All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.
Je sais que Union ALLS peut être déroutant dans le meilleur des cas, en particulier avec les jointures, mais je reçois essentiellement une liste de clés int à partir de deux tables, puis je les rejoigne à un tiers qui contient les données dont j'ai besoin (les clés des deux tables être présent dans la colonne jointe sur le Data
table.
La solution
Vous devez vous assurer que les deux ensembles de résultats ont les mêmes colonnes:
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)
Veuillez noter que la deuxième partie du UNION ALL
Maintenant, renvoie toujours 0 pour le Rownum. Si vous voulez avoir la colonne Rownum pour le résultat du UNION ALL
Vous avez besoin d'une autre sous-requête:
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
Votre deuxième sélection dans votre syndicat ne renvoie pas le même nombre de colonnes, d'où le problème.
Essayer:
;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