SQL Server: сопоставление записей на основе 3 таблиц - PullRequest
0 голосов
/ 21 февраля 2019

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

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

Таблица 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

Можно увидеть, как А представляет авуары, 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

EDIT 2 Спасибо посту Марлина Пирса, вот запрос, который возвращаетрезультат, который я ищу:

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

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

1 Ответ

0 голосов
/ 21 февраля 2019

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

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

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
...