#sql-server #tsql
#sql-server #tsql
Вопрос:
Мой вопрос: у меня есть две таблицы: таблица A имеет два столбца (KeyA и Match), а таблица B имеет два столбца (KeyB и Match). Я хочу сравнить со столбцом «Совпадение».
Если в таблице A есть 3 строки с определенным «совпадением», а в таблице B — 2 строки, объединение вернет мне все комбинации (в данном случае 6). Я хочу, чтобы он сопоставил столько, сколько сможет, а затем ОБНУЛИЛ остальные.
Итак, он сопоставил бы первую «KeyA» с первой «KeyB», вторую «KeyA» со второй «KeyB», а затем сопоставил бы третью «KeyA» с NULL, поскольку в таблице B есть только две строки для этого «Совпадения». Порядок на самом деле не имеет значения, если совпадают 2 строки, а затем одно значение из таблицы A возвращается с нулевым значением для значения таблицы B. Это не похоже на ВНУТРЕННЕЕ или ВНЕШНЕЕ ОБЪЕДИНЕНИЕ.
Я надеюсь, что это имеет смысл, это было трудно выразить четко, и было трудно найти ключевые слова для поиска.
РЕДАКТИРОВАТЬ: ВНУТРЕННЕЕ / ВНЕШНЕЕ объединение будет сопоставлять все значения таблицы A со всеми значениями таблицы B. Как только значение B «израсходовано», я не хочу, чтобы оно совпадало с любыми другими значениями A.
Пример: Таблица A (KeyA, Match)
(1, «a»)
(2, «a»)
(3, «a»)
Таблица B (KeyB, Match)
(11, «a»)
(12, «a»)
Желаемый результат (KeyA, Match, KeyB): (1, «a», 11)
(2, «a», 12)
(3, «a», NULL)
Комментарии:
1. Может быть, я слишком плотный, но я не вижу, чем ваше описание отличается от ВНЕШНЕГО СОЕДИНЕНИЯ СЛЕВА (с таблицей A слева). Не могли бы вы предоставить несколько примеров строк и ожидаемый результат, чтобы сделать его более понятным?
2. Похоже, вам нужен
OUTER JOIN
, но некоторые примеры данных помогут прояснить это.3. Можете ли вы предоставить некоторые примеры данных для каждой таблицы и как должен выглядеть результат запроса?
4. пример вывода прояснит ситуацию…
Ответ №1:
Вы можете использовать partition by
для нумерации строк для каждого значения match . Затем вы можете использовать full outer join
для заполнения строк за совпадение. Например:
declare @A table (KeyA int, match int)
insert @A values (1,1), (2,1), (3,1), (4,2), (5,2), (6,2)
declare @B table (KeyB int, match int)
insert @B values (1,1), (2,1), (3,2)
select *
from (
select row_number() over (partition by match order by KeyA) as rn
, *
from @A
) as A
full outer join
(
select row_number() over (partition by match order by KeyB) as rn
, *
from @B
) as B
on A.match = B.match
and A.rn = B.rn
Ответ №2:
declare @TableA table(ID int, Name varchar(10))
declare @TableB table(ID int, Name varchar(10))
insert into @TableA values(1, 'a'), (1, 'b'), (1, 'c')
insert into @TableB values (1, 'A'), (1, 'B')
insert into @TableA values(2, 'a'), (2, 'b')
insert into @TableB values (2, 'A'), (2, 'B'), (2, 'C')
;with A as
(
select *,
row_number() over(partition by ID order by Name) as rn
from @TableA
),
B as
(
select *,
row_number() over(partition by ID order by Name) as rn
from @TableB
)
select A.ID as AID,
A.Name as AName,
B.ID as BID,
B.Name as BName
from A
full outer join B
on A.ID = B.ID and
A.rn = B.rn
Результат:
AID AName BID BName
----------- ---------- ----------- ----------
1 a 1 A
1 b 1 B
1 c NULL NULL
2 a 2 A
2 b 2 B
NULL NULL 2 C
Ответ №3:
SELECT
ar.Match
COALESCE(ar.RowN, br.RowN) AS RowNumber
ar.KeyA
br.KeyB
FROM
( SELECT KeyA
, Match
, ROW_NUMBER() OVER(PARTITION BY Match) AS RowN
) AS ar
LEFT JOIN --- or FULL JOIN
( SELECT KeyB
, Match
, ROW_NUMBER() OVER(PARTITION BY Match) AS RowN
) AS br
ON br.Match = ar.Match
AND br.RowN = ar.RowN
Комментарии:
1. Что, если в B больше строк для определенного соответствия?
2. Да, ОП неясен. A
FULL JOIN
необходим, если есть такая возможность.
Ответ №4:
Я думаю, то, что вы ищете, называется перекрестным соединением или декартовым произведением.
http://www.sqlguides.com/sql_cross_join.php
редактировать — Хм, теперь я на самом деле не уверен.
Ответ №5:
Насколько я могу понять, то, что вы ищете FULL JOIN
, — это или также называется CROSS JOIN
.
Проверьте эту ссылку. В нем есть хорошее объяснение всех типов объединений: