SQL Server объединяет несколько CTE - PullRequest
0 голосов
/ 18 мая 2019

У меня есть 4 общих табличных выражения, каждое из которых содержит 2 столбца (RowNumber, AccountNumber), но содержат записи переменных в каждом CTE в зависимости от параметров запроса. Цель состоит в том, чтобы сохранить все ненулевые номера счетов вверху для каждого CTE после присоединения.

Я присоединяюсь к 4 CTE, используя FULL Join на основе RowNumber. Проблема, которую я получаю, состоит в том, что последовательность AccountNumber не является непрерывной, то есть в некоторых случаях она содержит некоторые нулевые значения между Accountnumber. Я хочу, чтобы все ненулевые значения всегда были объединены, а сверху - пустыми значениями. Количество AccountNumber в каждом CTE всегда различно.

SELECT​
  ISNULL(Cte_FirstYear.AccountNumber,'') as FirstYear,​
  ISNULL(Cte_SecondYear.AccountNumber,'') as SecondYear,​
  ISNULL(cte_ThirdYear.AccountNumber,'') as ThirdYear,​
  ISNULL(cte_FourthYear.AccountNumber,'') as FourthYear​
FROM cte_ThirdYear​
FULL OUTER JOIN​
cte_FirstYear
on ​
cte_ThirdYear.RowNumber=cte_FirstYear.RowNumber​​
full outer join  Cte_SecondYear​
on ​
cte_ThirdYear.RowNumber=Cte_SecondYear.RowNumber​​
full outer join  cte_FourthYear​
on ​
cte_ThirdYear.RowNumber=cte_FourthYear.RowNumber​​

Вот как я получаю вывод;

FirstYear SecondYear ThirdYear FourthYear
1           2           3         4
5           6           7         1
            9          NULL      NULL
                       NULL
                        9         9
                        10       NULL            

Здесь ожидаемый результат;

FirstYear SecondYear ThirdYear FourthYear
1           2           3         4
5           6           7         1
            9           9         9
                        10

Ответы [ 2 ]

1 голос
/ 18 мая 2019

Основано на объяснении @Donnie в ссылке

При перекрестном соединении получается декартово произведение между двумя таблицами, возвращающее все возможные комбинации всех строк.В нем нет условия on, потому что вы просто соединяете все со всем.

Полное внешнее соединение - это комбинация левого внешнего и правого внешнего соединения.Он возвращает все строки в обеих таблицах, которые соответствуют условию where запроса, и в тех случаях, когда условие on для этих строк не может быть выполнено, он вводит нулевые значения для незаселенных полей.

Вы можетедобавьте эту строку, чтобы игнорировать:
on cte_ThirdYear.RowNumber=cte_FirstYear.RowNumber​​ and on ​ cte_ThirdYear.RowNumber is not null and cte_FirstYear.RowNumber​​ is not null

Прочитайте этот pdf: http://stevestedman.com/wp-content/uploads/TSqlJoinTypePoster1.pdf

enter image description here

0 голосов
/ 18 мая 2019

Я создал другой CTE, который берет максимальное количество записей от 4 ctes и генерирует RowNumber 1 до N (Макс. Количество записей в 4 CTE) и соединил все 4 CTE с ним, используя LEFT JOIN.Вот как я изменил запрос для достижения результата:

Cte_Max(RowNumber) AS (
SELECT  TOP 
(
select max(c)  from 
(
select count(*) c from cte_FirstYear
UNION
select count(*) c from Cte_SecondYear
UNION
select count(*) c from cte_ThirdYear
UNION
select count(*) c from cte_FourthYear
) x
)
ROW_NUMBER() OVER (ORDER BY c1.id asc) as  RowNumber
FROM          syscolumns AS c1
CROSS JOIN    syscolumns AS c2
)

select 
ISNULL(cte_FirstYear.AccountNumber,'') as  FirstYear,​
ISNULL(Cte_SecondYear.AccountNumber,'') as SecondYear,​
ISNULL(cte_ThirdYear.AccountNumber,'') as ThirdYear,​
ISNULL(cte_FourthYear.AccountNumber,'') as FourthYear
from Cte_Max
LEFT join cte_FirstYear
on
Cte_Max.RowNumber=cte_FirstYear.RowNumber
LEFT join 
Cte_SecondYear
on 
Cte_Max.RowNumber=Cte_SecondYear.RowNumber
LEFT join 
cte_ThirdYear
on
Cte_Max.RowNumber =cte_ThirdYear.RowNumber
LEFT join 
cte_FourthYear
on
Cte_Max.RowNumber =cte_FourthYear.RowNumber
ORDER BY Cte_Max.RowNumber
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...