SQL Server: сопоставление записей на основе 3 таблиц

Я пытаюсь сопоставить записи между тремя таблицами, две таблицы — это данные для сопоставления, третья таблица — это центральная таблица, которая указывает мне, как должны сопоставляться записи.

Пример будет понятнее, чем длинная речь:

Таблица 1

Value1  A1  B1  C1
------------------
  0.1   1   b   z
  0.2   4   b   z
  1.1   5   b   z
  1.5   5   c   y
  2.5   7   c   x

Таблица 2

Value2  A2  B2  C2
------------------
  0.5   1   d   z
  0.7   4   d   z
  2.3   7   d   z
  1.7   5   e   y
  1.9   7   e   x

Таблица 3

    BL  BR  C
   -----------
     d   b  z
     c   e  x
     c   e  y

Способ увидеть это так: A представляет холдинги, C — держатели, а B — даты. Таким образом, Таблица 1 сообщает мне, какие активы есть в некоторые даты, Таблица 2 сообщает мне то же самое в некоторые другие даты, и, наконец, Таблица 3 говорит мне, как сравнивать активы, например. для держателя C = z я хочу сравнить владения между датами B = d и датой B = b (на практике таблицы 1 и 2 совпадают).

Итак, я ищу таблицу для сравнения холдингов, принимая во внимание холдинги, которые были созданы, и холдинги, которые были удалены. Я ищу что-то вроде этого:

Value1 A1  B1  C1  BR BL C  A2 B2 C2 Value2
-------------------------------------------
  0.1   1   b   z   b d  z  1   d  z  0.5
  0.2   4   b   z   b d  z  4   d  z  0.7
  1.1   5   b   z   b d  z
                    b d  z  7   d  z  2.3
  1.5   5   c   y   c e  y  5   e  y  1.7
  2.5   7   c   x   c e  x  7   e  x  1.9

Таким образом, записи совпадают только в том случае, если A1 = A2, C1 = C2 и B1 = BR, B2 = BL, в противном случае он пуст с той или иной стороны.

Я надеюсь, что это ясно. Я пробовал различные подходы (левое/правое/полное соединение) без успеха. Приветствуется любая помощь!

Спасибо

РЕДАКТИРОВАТЬ Добавление примера кода. Это T-SQL.

CREATE TABLE #T1  (Value1 FLOAT, A1 INT, B1 CHAR, C1 CHAR);  
CREATE TABLE #T2 (Value2 FLOAT, A2 INT, B2 CHAR, C2 CHAR);  
CREATE TABLE #T3 (BR CHAR, BL CHAR, C CHAR);  

INSERT INTO #T1  VALUES (0.1, 1, 'b', 'z'), 
                (0.2, 4, 'b', 'z'), 
                (1.1, 5, 'b', 'z'), 
                (1.5, 5, 'c', 'y'), 
                (2.5, 7, 'c', 'x');

INSERT INTO #T2  VALUES (0.5, 1, 'd', 'z'), 
                (0.7, 4, 'd', 'z'), 
                (2.3, 7, 'd', 'z'), 
                (1.7, 5, 'e', 'y'), 
                (1.9, 7, 'e', 'x');

INSERT INTO #T3  VALUES ('b', 'd', 'z'), 
                    ('c', 'e', 'x'),
                    ('c', 'e', 'y');

Пример запроса, который я пробовал.

SELECT 
    *
FROM #T3 
LEFT JOIN #T1 ON #T1.B1 = #T3.BR AND #T1.C1 = #T3.C
FULL JOIN #T2 ON #T2.B2 = #T3.BL AND #T2.C2 = #T3.C AND #T2.A2 = #T1.A1

Вот что я получаю результат. Близко, но я бы хотел, чтобы BR, BL и C никогда не были NULL, потому что после этого у меня есть некоторая логика в этих столбцах. Эти столбцы не обязательно должны быть нулевыми в последней строке, их можно сопоставить со строкой в ​​#T3.

Вся сложность в AND #T2.A2 = #T1.A1: если такая запись существует, я хочу, чтобы она совпадала, но если нет, я бы хотел, чтобы она вел себя так, как если бы второе соединение было ЛЕВЫМ СОЕДИНЕНИЕМ на #T2.B2 = #T3.BL AND #T2.C2 = #T3.C

РЕДАКТИРОВАТЬ 2 Благодаря сообщению Marlin Pierce, вот запрос, который возвращает результат, который я ищу:

SELECT Value1 A1,  B1,  C1,  BR, BL, C,  A2, B2, C2, Value2
FROM #T3 inner join #T1 on #T1.B1 = #T3.BR AND #T1.C1 = #T3.C
         inner join #T2 on #T2.B2 = #T3.BL AND #T2.C2 = #T3.C AND #T2.A2 = #T1.A1

UNION ALL

SELECT Value1 A1,  B1,  C1,  BR, BL, C,  A2, B2, C2, Value2
FROM #T3 left join #T2 on #T2.B2 = #T3.BL and #T2.C2 = #T3.C
         full join #T1 on #T1.B1 = #T3.BR and #T1.C1 = #T3.C AND #T2.A2 = #T1.A1
WHERE #T1.A1 is NULL

UNION ALL

SELECT Value1 A1,  B1,  C1,  BR, BL, C,  A2, B2, C2, Value2
FROM #T3 left join #T1 on #T1.B1 = #T3.BR and #T1.C1 = #T3.C
         full join #T2 on #T2.B2 = #T3.BL and #T2.C2 = #T3.C AND #T2.A2 = #T1.A1
WHERE #T2.A2 is NULL

Однако я хотел бы найти более эффективный/элегантный способ сделать это, если он существует.

Что это за технология SQL? Опубликуйте, что вы пробовали для своих запросов. Также у вас есть 3 таблицы, из которых вы пытаетесь получить данные. Попробуйте сначала сделать только 2, затем получите данные, а затем добавьте 3-й.

Brad 21.02.2019 18:37

«Я пробовал разные подходы». Где один из них? Я этого не вижу. SO не является сайтом службы бесплатного кодирования. Опубликуйте свой запрос. Если не получится, постараемся помочь.

Eric 21.02.2019 18:42

Похоже, вам нужно ПОЛНОЕ СОЕДИНЕНИЕ, опубликуйте свою попытку использовать его, чтобы мы могли его отладить.

Tab Alleman 21.02.2019 18:58

Добавлены примеры кодов. Я пробовал различные комбинации объединений, но не получил того, что искал (это таблица, написанная от руки в первой части сообщения).

Loupiol 21.02.2019 19:36

Четкое описание понятнее, чем нечеткое описание. Используйте достаточно слов, предложений и ссылок на примеры, чтобы сказать, какие строки появляются в результате с точки зрения строк, которые появляются во входных данных. Т.е. указать обстоятельства, при которых в результате появляется строка вида (A1, B1, C1, BR, BL, C, A2, B2, C2, Value2). Например, когда строка (t1.A1, t1.B1, t1.C1) появляется в T1 & A1=t1.A1 & B1=t1.B1 & C1=t1.C1 & ... ИЛИ ....

philipxy 21.02.2019 22:53
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
859
1

Ответы 1

Я не уверен, но я думаю, что это даст вам результаты, которые вы ищете. (То, что вы ищете, немного неясно.)

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

SELECT Value1 A1,  B1,  C1,  BR, BL, C,  A2, B2, C2, Value2
FROM T3 inner join T1 on T1.B1 = T3.BR
        inner join T2 on T2.B2 = T3.BL
WHERE A1 = A2 and C1 = C2

UNION ALL

SELECT Value1 A1,  B1,  C1,  BR, BL, C,  A2, B2, C2, Value2
FROM T3 inner join T1 on T1.B1 = T3.BR
        left outer join T2 on T2.B2 = T3.BL
WHERE T2.B2 is NULL

UNION ALL

SELECT Value1 A1,  B1,  C1,  BR, BL, C,  A2, B2, C2, Value2
FROM T3 inner join T2 on T2.B2 = T3.BL
        left outer join T1 on T1.B1 = T3.BR
WHERE T1.B1 is NULL

В результаты не будут включены записи из таблицы T3, которые не соответствуют ни T1, ни T2, но я не понимаю, нужны ли они вам.

Marlin Pierce 21.02.2019 19:59

Привет. То, что вы написали, не совсем то, что я ищу, но я понял вашу идею и преобразовал ее в запрос, который я ищу (см. Мое редактирование). Я действительно ищу решение, которое могло бы быть более элегантным/эффективным.

Loupiol 21.02.2019 20:05

Другие вопросы по теме