Я чувствую себя грязно, написав это. Это ужасный код, потому что это , а не , как следует использовать SQL. Это не дает требуемых точных результатов, но это потому, что совпадение друзей и продуктов в любом случае произвольно, поэтому я наложил свой собственный заказ:
;with OrderedProducts as (
select Customer,Product,ROW_NUMBER() OVER (PARTITION BY Customer ORDER BY Product) rn
from @Products
), OrderedFriends as (
select Customer,Friend,ROW_NUMBER() OVER (PARTITION BY Customer ORDER BY Friend) rn
from @Friends
)
select
CASE WHEN COALESCE(op.rn,ofr.rn) = 1 THEN COALESCE(op.Customer,ofr.Customer) END,
op.Product,
ofr.Friend
from
OrderedProducts op
full outer join
OrderedFriends ofr
on
op.Customer = ofr.Customer and
op.rn = ofr.rn
order by COALESCE(op.Customer,ofr.Customer),COALESCE(op.rn,ofr.rn)
Дает результат:
Product Friend
---- ------- ------
A Bike Andrew
NULL Boat John
NULL Car NULL
B Bar Baz
NULL Foo NULL
По сути, так как у вас, кажется, нет ни одного, я разработал свое собственное правило для случаев, когда две строки совпадают между этими двумя таблицами, - чтобы строки были пронумерованы в алфавитном порядке для каждого клиента, а затем использовал эти номера строк для создания уникальные совпадения между таблицами.
* * * * * * * * * * * * * * * * * * * * * Для того, чтобы иметь дело с клиентами с друзьями, без продуктов, без продуктов, без друзей. CASE
был единственным способом, которым я мог понять, чтобы имя клиента отображалось только в одном ряду.
И вот как я настроил пример данных:
declare @Products table (
Customer char(1) not null,
Product varchar(4) not null
)
insert into @Products (Customer , Product) values
( 'A' , 'Car'),
( 'A' , 'Bike'),
( 'A' , 'Boat'),
( 'B' , 'Foo'),
( 'B' , 'Bar')
declare @Friends table (
Customer char(1) not null,
Friend varchar(6) not null
)
insert into @Friends (Customer , Friend) values
( 'A' , 'John'),
( 'A' , 'Andrew'),
( 'B' , 'Baz')