Соединение SQL Left с дублирующимися записями, но с другим значением - PullRequest
0 голосов
/ 30 сентября 2019

Ниже приведены две таблицы и требуемый результат.

enter image description here

Для простоты ниже приведен код таблицы.

CREATE TABLE #A(CustNo varchar(100), TranID varchar (100), ChkID float)
insert into #A values

('A','A123',200),
('A','A123',100),
('B','B36',200)

CREATE TABLE #B(VCustNo varchar(100), VTransID varchar (100), VCode varchar(100))
INSERT INTO #B VALUES
('A','A123','NN1'),
('A','A123','PP2'),
('A','A123','QQ3') 

и я попытался с помощью следующего запроса, который дает мне неправильный вывод.

SELECT A.CustNo, A.TranID,A.ChkID, B1.VCustNo, B1.VTransID, B1.VCode
FROM #A A
LEFT JOIN (select VCustNo, min(VTransID) as VTransID, min(VCode) as VCode  from #b group by VCustNo) B1
    ON A.CustNo = B1.VCustNo and a.TranID = B1.VTransID 

enter image description here

Ответы [ 3 ]

1 голос
/ 30 сентября 2019

Похоже, вы пытаетесь создать искусственное соединение между таблицами на основе порядка строк. Это не сработает, потому что строки не имеют порядка, но вы можете попробовать это с чем-то вроде:

SELECT A.CustNo, A.TranID,A.ChkID, B.VCustNo, B.VTransID, B.VCode
FROM 
  (SELECT *, ROW_NUMBER() OVER(PARTITION BY CustNo ORDER BY ChkId DESC) as fakeid FROM #A) A
  FULL OUTER JOIN
  (SELECT *, ROW_NUMBER() OVER(PARTITION BY VCustNo ORDER BY VCode ASC) as Vfakeid FROM #B) B
  ON 
    A.CustNo = B.VCustNo and
    a.TranID = B1.VTransID and
    a.FakeID = B.VFakeID 

Похоже, A.ChkId - это нисходящий порядок, а b.VCodeявляется возрастающим порядком, поэтому, если мы присваиваем порядковый номер в этих порядках каждому из наборов данных, мы можем присоединиться к нему:

CREATE TABLE #A(CustNo varchar(100), TranID varchar (100), ChkID float)
insert into #A values

('A','A123',200),
('A','A123',100),
('B','B36',200)

CREATE TABLE #B(VCustNo varchar(100), VTransID varchar (100), VCode varchar(100))
INSERT INTO #B VALUES
('A','A123','NN1'),
('A','A123','PP2'),
('A','A123','QQ3') 

SELECT A.CustNo, A.TranID,A.ChkID, B.VCustNo, B.VTransID, B.VCode
    FROM 
      (SELECT *, ROW_NUMBER() OVER(PARTITION BY CustNo ORDER BY ChkId DESC) as fakeid FROM #A) A
      FULL OUTER JOIN
      (SELECT *, ROW_NUMBER() OVER(PARTITION BY VCustNo ORDER BY VCode ASC) as Vfakeid FROM #B) B
      ON A.CustNo = B.VCustNo and and a.TranID = B1.VTransID and a.FakeID = B.VFakeID
GO
CustNo | TranID | ChkID | VCustNo | VTransID | VCode
:----- | :----- | ----: | :------ | :------- | :----
A      | A123   |   200 | A       | A123     | NN1  
A      | A123   |   100 | A       | A123     | PP2  
<em>null</em>   | <em>null</em>   |  <em>null</em> | A       | A123     | QQ3  
B      | B36    |   200 | <em>null</em>    | <em>null</em>     | <em>null</em> 

дБ <> fiddle здесь

Я говорю, что это не сработает, потому что как только правило «chkid убывающий, vcode axcending» перестает быть верным, вы не получите то, что хотите, нобольше нет доступных данных для присоединения. Я бы порекомендовал вам добавить правильные реляционные данные, а не полагаться на шаблон смещающейся строки - любые данные, вставленные в любую из этих таблиц, могут нарушить это отношение в любое время (если вы добавите chkid 150, то chkid 100 больше не будет относиться к vcode pp2)

1 голос
/ 30 сентября 2019

использовать полное внешнее соединение

DEMO

select A.CustNo, A.TranID,A.ChkID, B1.VCustNo, B1.VTransID, B1.VCode from
(
SELECT A.CustNo, A.TranID,A.ChkID,row_number() over(partition by custno order by chkid desc) as rn1
FROM #A A
)A
full outer join
(
select B1.VCustNo, B1.VTransID, B1.VCode,row_number() over(partition by VCustNo order by VCode) as rn2
from #B B1
)B1 ON A.CustNo = B1.VCustNo and a.TranID = B1.VTransID 
    and rn1=rn2

ВЫХОД:

CustNo  TranID  ChkID   VCustNo VTransID    VCode
A       A123    200      A       A123       NN1
A       A123    100      A       A123       PP2
                         A       A123       QQ3
B       B36     200     
0 голосов
/ 30 сентября 2019

использование row_number() и полное внешнее соединение

select a.*,b.* from

(
select *,row_number() over(order by CustNo) rn1 from #A
) a
full outer join
(
select *,row_number() over(order by VCustNo) rn2 from #B
) b on a.CustNo=b.VCustNo and a.TranID=b.VTransID and a.rn1=b.rn2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...