Ищете особый способ присоединиться на SQL сервере - PullRequest
0 голосов
/ 28 февраля 2020

Я хотел бы объединить две таблицы, но не смог найти какие-либо существующие объединения (я попытался сделать это слева, справа, полностью, поперечно). Я хочу объединить таблицу 1 и таблицу 2 в таблицу 3. Порядок данных был основан на хронологическом порядке, и я хотел бы видеть тот же порядок в требуемой таблице.

ТАБЛИЦА 1:

Студент ---- Оценка1
A ------------ 90
A ------------ 80
B ----- ------- 85
B ------------ 60
C ------------ 50
C ------------ 40

Таблица2:

Студент ---- Оценка2
A ------------ 66
A ------------ 70
A ------------ 85
B ------------ 60
C ------------ 40

Таблица 3: Желаемая таблица

Студент ---- Счет1 ----- Счет2
A ------------ 90 ----------- 66
A ------------ 80 ----- ------ 70
A ------------ ноль ----------- 85
B ---------- - 85 ----------- 60
B ------------ 60 ----------- ноль
C ------------ 50 ----------- 40
C ------------ 40 ------ ----- ноль

Спасибо!

Ответы [ 2 ]

1 голос
/ 28 февраля 2020

Хорошо, нам нужно в первую очередь попытаться найти способ добавить позиционный столбец в вашу таблицу во время выполнения. Это можно сделать с помощью функции 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
0 голосов
/ 28 февраля 2020

Ну, технически:

with t1 as (
    select    *, ord = row_number() over(partition by student order by score1 desc)
    from      table1 
),

t2 as (
    select    *, ord = row_number() over(partition by student order by score2)
    from      table1 
)

select    student = isnull(t1.student, t2.student),
          t1.score1,
          t2.score2
from      t1
full join t2 on t1.student = t2.student and t1.ord = t2.ord;

Но я сомневаюсь, что вы хотите упорядочить оценки в таблице 1 в порядке убывания и оценки в таблице 2 в порядке возрастания. Так что вам придётся придавить это. Есть ли колонка для времени проведения теста? Наверное, лучше заказать по этому.

Еще лучше, сделайте это в своем программном обеспечении, например, с SSRS, отчетами о кристаллах и т. П. Я говорю это потому, что полагаю, что это необходимо для отчетности, когда строки больше не представляют «записи».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...