Объединение 2 таблиц для извлечения всех значений из каждой

У меня есть 2 таблицы, к которым я хочу присоединиться определенным образом, чтобы получить все данные в каждой, даже если некоторые из объединенных полей могут отсутствовать в каждой, что-то вроде полного внешнего соединения.

Таблица А

+--------+-------+------+-------+
| Group  | Name  | Year | Value |
+--------+-------+------+-------+
|      1 | Joe   | 2018 |    23 |
|      1 | Joe   | 2019 |    56 |
|      2 | Fred  | 2019 |    89 |
|      2 | Fred  | 2020 |    45 |
+--------+-------+------+-------+

Таблица Б

+-------+------+------+-------+----------+
| Group | Name | Year | Scope |  Status  |
+-------+------+------+-------+----------+
|     1 | Joe  | 2019 |    78 | Approved |
|     2 | Fred | 2018 |    12 | Approved |
|     2 | Fred | 2020 |   987 | Started  |
|     2 | Fred | 2021 |   321 | Sent     |
+-------+------+------+-------+----------+

Я хочу присоединиться к A.Group = B.Group и A.Year = B.Year, но когда год существует на одном, а не на другом, на другой стороне отображается нуль. Таким образом, будет строка для каждого имени для каждого года и соответствующих значений или 0/null в зависимости от того, что доступно. Таким образом, результат для этого примера должен выглядеть так:

Таблица А и Б

+---------+--------+--------+---------+---------+--------+--------+---------+----------+
| A.Group | A.Name | A.Year | A.Value | B.Group | B.Name | B.Year | B.Scope | B.Status |
+---------+--------+--------+---------+---------+--------+--------+---------+----------+
|       1 | Joe    |   2018 |      23 |       1 | Joe    |   2018 |       0 | <null>   |
|       1 | Joe    |   2019 |      56 |       1 | Joe    |   2019 |      78 | Approved |
|       1 | Joe    |   2020 |       0 |       1 | Joe    |   2020 |       0 | <null>   |
|       1 | Joe    |   2021 |       0 |       1 | Joe    |   2021 |       0 | <null>   |
|       2 | Fred   |   2018 |       0 |       2 | Fred   |   2018 |      12 | Approved |
|       2 | Fred   |   2019 |      89 |       2 | Fred   |   2019 |       0 | <null>   |
|       2 | Fred   |   2020 |      45 |       2 | Fred   |   2020 |     987 | Started  |
|       2 | Fred   |   2021 |       0 |       2 | Fred   |   2021 |     321 | Sent     |
+---------+--------+--------+---------+---------+--------+--------+---------+----------+

person David_S53    schedule 15.01.2020    source источник
comment
минимальный воспроизводимый пример, пожалуйста. (В том числе СУБД.) Что вы умеете делать? Вы знаете, что такое внешнее соединение? См. Как спросить, другой справочный центр. ссылки и тексты со стрелкой голосования при наведении курсора мыши. Ваше описание того, что вы хотите, не ясно. Бесполезно говорить, что вы хотите что-то вроде объединения. Вы не можете ожидать, что сможете закодировать решение, если вы не можете четко указать условие для того, чтобы строка значений была в результате.   -  person philipxy    schedule 15.01.2020


Ответы (2)


Если ваша база данных поддерживает CTE, вы можете использовать CTE. В другом случае вы можете использовать SUB QUERY для замены CTE, воспользовавшись приведенной ниже логикой для достижения желаемого результата.

ДЕМО ЗДЕСЬ

WITH CTE_Group([Group],Name)
AS
(
    SELECT DISTINCT [Group],Name FROM tab_A
    UNION 
    SELECT DISTINCT [Group],Name FROM tab_B
),
CTE_Year(Year)
AS
(
    SELECT DISTINCT Year FROM tab_A
    UNION 
    SELECT DISTINCT Year FROM tab_B
)
SELECT A.[Group],A.Name,B.Year,ISNULL(C.Value,0) Value,
A.[Group],A.Name,B.Year,ISNULL(D.Scope,0) Scope,D.Status
FROM CTE_Group A
CROSS APPLY CTE_Year B
LEFT JOIN Tab_A C ON A.[Group] = C.[Group] AND B.Year = C.Year
LEFT JOIN Tab_B D ON A.[Group] = D.[Group] AND B.Year = D.Year
ORDER BY 1,3

Выход-

Group   Name    Year    Value   Group   Name    Year    Scope   Status
1       Joe     2018    23      1       Joe     2018    0   
1       Joe     2019    56      1       Joe     2019    78      Approved
1       Joe     2020    0       1       Joe     2020    0   
1       Joe     2021    0       1       Joe     2021    0   
2       Fred    2018    0       2       Fred    2018    12      Approved
2       Fred    2019    89      2       Fred    2019    0   
2       Fred    2020    45      2       Fred    2020    987     Started
2       Fred    2021    0       2       Fred    2021    321     Sent
person mkRabbani    schedule 15.01.2020
comment
Фантастика, это делает это. Можно видеть, что это также подходит для случаев, когда у имени может не быть года ни в одной из таблиц, и по-прежнему будет отображаться строка для них независимо от 0/null. А также подбирает любые дополнительные годы, добавленные, чтобы сделать то же самое. Спасибо за вашу помощь! - person David_S53; 15.01.2020
comment
Пожалуйста, @David_S53. Приятно слышать, что это помогло :) Пожалуйста, не забудьте также проголосовать за ;) - person mkRabbani; 15.01.2020

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

Select
A.Group, A.Name, A.Year, coalesce(A.Value,0) as A.Value, B.Group, B.Name, B.Year, B.Scope, B.Status
From TableA A cross join TableB B on A.Group = B.Group and A.Year = B.Year
person zip    schedule 15.01.2020