Подтвердить что ты не робот

Полное объединение нескольких таблиц в одни и те же столбцы

У меня есть четыре таблицы:

╔═══╦════╗ ╔═══╦════╗ ╔═══╦════╗ ╔═══╦════╗
║ K ║ V1 ║ ║ K ║ V2 ║ ║ K ║ V3 ║ ║ K ║ V4 ║
╠═══╬════╣ ╠═══╬════╣ ╠═══╬════╣ ╠═══╬════╣
║ A ║  1 ║ ║ B ║  2 ║ ║ B ║  3 ║ ║ C ║  6 ║
║ C ║  4 ║ ║ D ║  7 ║ ║ C ║  5 ║ ║ D ║  8 ║
╚═══╩════╝ ╚═══╩════╝ ╚═══╩════╝ ╚═══╩════╝

Мне нужно соединить их столбцом K и выбрать V1, V2, V3 и V4:

╔═══╦══════╦══════╦══════╦══════╗
║ K ║  V1  ║  V2  ║  V3  ║  V4  ║
╠═══╬══════╬══════╬══════╬══════╣
║ A ║ 1    ║ NULL ║ NULL ║ NULL ║
║ B ║ NULL ║ 2    ║ 3    ║ NULL ║
║ C ║ 4    ║ NULL ║ 5    ║ 6    ║
║ D ║ NULL ║ 7    ║ NULL ║ 8    ║
╚═══╩══════╩══════╩══════╩══════╝

Один из способов решить эту проблему:

DECLARE @T1 TABLE (K VARCHAR(1), V1 INT);
DECLARE @T2 TABLE (K VARCHAR(1), V2 INT);
DECLARE @T3 TABLE (K VARCHAR(1), V3 INT);
DECLARE @T4 TABLE (K VARCHAR(1), V4 INT);

INSERT INTO @T1 VALUES ('A', 1), ('C', 4);
INSERT INTO @T2 VALUES ('B', 2), ('D', 7);
INSERT INTO @T3 VALUES ('B', 3), ('C', 5);
INSERT INTO @T4 VALUES ('C', 6), ('D', 8);

SELECT COALESCE(t1.K, t2.K, t3.K, t4.K) [K], V1, V2, V3, V4
FROM @T1 t1
FULL JOIN @T2 t2 ON t2.K = t1.K
FULL JOIN @T3 t3 ON t3.K = t1.K OR t3.K = t2.K
FULL JOIN @T4 t4 ON t4.K = t1.K OR t4.K = t2.K OR t4.K = t3.K
ORDER BY 1;

Но это хорошо работает только для этого простого примера, если у меня больше Ks (условия объединения) и Vs, условия соединения в итоге намного сложнее.

Как можно улучшить этот запрос?

4b9b3361

Ответ 1

Существует несколько способов, но я думаю, что наиболее популярным является следующее:

select allk.k, t1.c1, t2.v2, t3.v3, t4.v4
from (select k from t1 union 
      select k from t2 union
      select k from t3 union
      select k from t4
     ) allk left outer join
     t1
     on allk.k = t1.k left outer join
     t2
     on allk.k = t2.k left outer join
     t3
     on allk.k = t3.k left outer join
     t4
     on allk.k = t4.k;

Если у вас есть отдельная таблица всех значений k, вы можете использовать это вместо подзапроса allk.

Более простой способ написать запрос full outer join - использовать coalesce():

SELECT COALESCE(t1.K, t2.K, t3.K, t4.K) [K], V1, V2, V3, V4
FROM @T1 t1 FULL JOIN
     @T2 t2
     ON t2.K = t1.K FULL JOIN
     @T3 t3
     ON t3.K = coalesce(t1.K, t2.K) FULL JOIN
     @T4 t4
     ON t4.K = coalesce(t1.K, t2.K, t3.k);

И третий метод - это метод union all/group by:

select k, max(v1) as v1, max(v2) as v2, max(v3) as v3, max(v4) as v4
from (select k, v1, NULL as v2, NULL as v3, NULL as v4
      from t1 union all
      select k, NULL as v1, v2, NULL as v3, NULL as v4
      from t2 union all
      select k, NULL as v1, NULL as v2, v3, NULL as v4
      from t3 union all
      select k, NULL as v1, NULL as v2, NULL as v3, v4
      from t4
     ) t
group by k;