Хорошо, нам нужно в первую очередь попытаться найти способ добавить позиционный столбец в вашу таблицу во время выполнения. Это можно сделать с помощью функции ROW_NUMBER ():
SELECT *, ROW_NUMBER() OVER (PARTITION BY Student ORDER BY Student) Position FROM Table1
SELECT *, ROW_NUMBER() OVER (PARTITION BY Student ORDER BY Student) Position FROM Table2
Это создает хороший столбец Position в нашем результате:
Student Score1 Position
---------- ----------- --------------------
A 90 1
A 80 2
B 85 1
B 60 2
C 50 1
C 40 2
(6 rows affected)
Student Score2 Position
---------- ----------- --------------------
A 66 1
A 70 2
A 85 3
B 60 1
C 40 1
(5 rows affected)
Теперь нам нужно объединить эти два временных результата. Поскольку вы хотите включить все строки из каждой таблицы, оставляя пустыми (NULL) пробелы, оставшиеся от несоответствующих строк. FULL OUTER JOIN
приходит на помощь, во всей красе:
SELECT *
FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY Student ORDER BY Student) Position FROM Table1) T1
FULL OUTER JOIN
(SELECT *, ROW_NUMBER() OVER (PARTITION BY Student ORDER BY Student) Position FROM Table2) T2
ON T1.Student = T2.Student AND T1.Position = T2.Position
Мы получаем это:
Student Score1 Position Student Score2 Position
---------- ----------- -------------------- ---------- ----------- --------------------
A 90 1 A 66 1
A 80 2 A 70 2
NULL NULL NULL A 85 3
B 85 1 B 60 1
B 60 2 NULL NULL NULL
C 50 1 C 40 1
C 40 2 NULL NULL NULL
(7 rows affected)
Теперь просто выберите то, что вас интересует:
SELECT COALESCE(T1.student, T2.student) Student,
T1.score1,
T2.score2
FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY Student ORDER BY Student) Position FROM Table1) T1
FULL OUTER JOIN
(SELECT *, ROW_NUMBER() OVER (PARTITION BY Student ORDER BY Student) Position FROM Table2) T2
ON T1.Student = T2.Student AND T1.Position = T2.Position
И вуаля:
Student score1 score2
---------- ----------- -----------
A 90 66
A 80 70
A NULL 85
B 85 60
B 60 NULL
C 50 40
C 40 NULL
(7 rows affected)
Имейте в виду, однако: со многими записями это не может быть наиболее эффективным способом хранения и извлечения ваших данных ...
Править : что было добавлено после принятия ответа
Действительно важно : поскольку в комментариях рождается небольшая диатриба, давайте констатируем очевидное.
Дизайн базы данных предложенный OP имеет много недостатков, во-первых, он основан на предположении, что порядок записей в таблице всегда будет таким, в который записи были вставлены.
Это не может быть правдой и мое решение не может работать должным образом, пока не будет реализован более надежный способ сортировки записей.
Было бы лучше добавить столбец CreatedAt
в обе таблицы типа datetime
в где хранить запись вставить дату:
ALTER TABLE dbo.Table1 ADD
CreatedAt datetime NOT NULL CONSTRAINT DF_Table1_CreatedAt DEFAULT getdate()
ALTER TABLE dbo.Table2 ADD
CreatedAt datetime NOT NULL CONSTRAINT DF_Table2_CreatedAt DEFAULT getdate()
* 1 040 * Это может позволить более безопасно упорядочить записи.
Решение изменится следующим образом:
SELECT COALESCE(T1.student, T2.student) Student,
T1.score1,
T2.score2
FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY Student ORDER BY CreatedAt) Position FROM Table1) T1
FULL OUTER JOIN
(SELECT *, ROW_NUMBER() OVER (PARTITION BY Student ORDER BY CreatedAt) Position FROM Table2) T2
ON T1.Student = T2.Student AND T1.Position = T2.Position