it-swarm.com.de

LEFT OUTER JOIN unter mehreren Bedingungen

Gibt es eine Möglichkeit, zwei Tabellen der Reihe nach zu verknüpfen?

Tabelle A (tatsächlich):

EX  STATUS  DLV     Actual FEE    Expected Fee
N    ACT    MAIL    1.25
N    ACT    EMAIL   1.25
N    ACT    PICKUP  0
N    NON    MAIL    0
N    NON    EMAIL   1.25
N    NON    PICKUP  0
Y                   0

Tabelle B (erwartet):

EX  STATUS  DLV     Expected FEE
N    ACT    MAIL    1.25
N    ACT    EMAIL   0
N    ACT    PICKUP  0
N    NON    MAIL    1.25
N    NON    EMAIL   0
N    NON    PICKUP  0
Y                   0

Tabelle A (erwartetes Ergebnis):

EX  STATUS  DLV     Actual FEE    Expected Fee
N    ACT    MAIL    1.25          1.25
N    ACT    EMAIL   1.25          0
N    ACT    PICKUP  0             0
N    NON    MAIL    0             1.25
N    NON    EMAIL   1.25          0
N    NON    PICKUP  0             0
Y                   0             0

Ich möchte die folgende Logik in den Join integrieren: A.EX = B.EX (Join on first)

aber dann auf die Kombination der anderen 3, da sie einzigartig sind.

Ich habe es versucht, aber es hat natürlich nicht funktioniert:

FROM
dbo.claims a
left outer join dbo.pricing p on a.EX = p.EX 
and a.STATUS = p.STATUS
and a.DLV = p.DLV 

Ich hatte gehofft, Tabelle B mit Tabelle A zu verknüpfen, um die erwartete Gebühr zu erhalten. Wenn Ex = Y, ist es 0, unabhängig von Status oder DLV. Wenn Ex = N, dann muss ich mich auf die beiden anderen Spalten verlassen.

Es tut mir leid, wenn das verwirrend ist.

1
Pweshee
create table tableA (EX char(1), STATUS char(3), DLV varchar(10), Actual_FEE decimal(18,2));
insert into tableA values
('N', 'ACT', 'MAIL',   1.25),
('N', 'ACT', 'EMAIL',  1.25),
('N', 'ACT', 'PICKUP', 0),
('N', 'NON', 'MAIL',   0),
('N', 'NON', 'EMAIL',  1.25),
('N', 'NON', 'PICKUP', 0),
('Y', null,  null,     0);
GO
 7 Zeilen betroffen 
create table tableB (EX char(1), STATUS char(3), DLV varchar(10), Expected_FEE decimal(18,2));
insert into tableB values
('N', 'ACT', 'MAIL',   1.25),
('N', 'ACT', 'EMAIL',  0),
('N', 'ACT', 'PICKUP', 0),
('N', 'NON', 'MAIL',   1.25),
('N', 'NON', 'EMAIL',  0),
('N', 'NON', 'PICKUP', 0),
('Y', null,  null,     0);
GO
 7 Zeilen betroffen 

Nach Ihrem erwarteten Ergebnis könnte es sein:

select    a.EX, a.STATUS, a.DLV, a.Actual_FEE, b.Expected_FEE
from      tableA a
left join (select distinct EX, STATUS, DLV, Expected_Fee
           from   tableB) b
on        a.EX = b.EX
and       (a.STATUS = b.STATUS OR b.STATUS IS NULL)
and       (a.DLV = b.DLV or b.DLV IS NULL)
GO
 EX | STATUS | DLV | Actual_FEE | Expected_FEE 
:  : ----- | : ----- | : --------- | : ----------- 
 N | ACT | MAIL | 1,25 | 1,25 
 N | ACT | E-MAIL | 1,25 | 0,00 
 N | ACT | ABHOLUNG | 0,00 | 0,00 
 N | NICHT | MAIL | 0,00 | 1,25 
 N | NICHT | E-MAIL | 1,25 | 0,00 
 N | NICHT | ABHOLUNG | 0,00 | 0,00 
 Y |  null  |  null  | 0,00 | 0,00 

dbfiddle --- (hier

4
McNets

Wenn beide Tabellen in STATUS und DLV konsistent null haben, wenn EX ein Y enthält, können Sie die beiden Spaltensätze mit EXISTS und INTERSECT abgleichen:

FROM
  dbo.claims AS a
  LEFT JOIN dbo.pricing AS p
    ON EXISTS
      (
        SELECT a.EX, a.STATUS, a.DLV
        INTERSECT
        SELECT p.EX, p.STATUS, p.DLV
      )

Dort werden die beiden Spaltensätze mit FROM-less SELECTs und dem INTERSECT-Operator als Zeilen abgeglichen, anstatt jede Spalte mit dem Operator = Separat mit ihrem Gegenstück abzugleichen. Der Unterschied besteht darin, dass in diesem Fall zwei Nullen als gleich angesehen werden. (Wenn Sie sie mit = Vergleichen, sind sie es nicht.)

Wenn Sie also, wie gesagt, die Zeilen Y konsistent als 'Y', NULL, NULL In beiden Tabellen speichern, können Sie mit dem obigen einfachen Umschreiben diese Zeilen abgleichen, wenn beide Tabellen sie haben.

4
Andriy M

Ähnlich wie bei McNets +1 (ich habe ein paar andere Sachen ausprobiert)

declare @tableA table (EX char(1) not null, STATUS char(3), DLV varchar(10), Actual_FEE decimal(18,2));
insert into @tableA values
('N', 'ACT', 'MAIL',   1.25),
('N', 'ACT', 'EMAIL',  1.25),
('N', 'ACT', 'PICKUP', 0),
('N', 'NON', 'MAIL',   0),
('N', 'NON', 'EMAIL',  1.25),
('N', 'NON', 'PICKUP', 0),
('Y', null,  null,     0); 

declare @tableB table (EX char(1) not null, STATUS char(3), DLV varchar(10), Expected_FEE decimal(18,2));
insert into @tableB values
('N', 'ACT', 'MAIL',   1.25),
('N', 'ACT', 'EMAIL',  0),
('N', 'ACT', 'PICKUP', 0),
('N', 'NON', 'MAIL',   1.25),
('N', 'NON', 'EMAIL',  0),
('N', 'NON', 'PICKUP', 0),
('Y', null,  null,     0);

select a.EX, a.STATUS, a.DLV, a.Actual_FEE, b.Expected_FEE  
from @tableA a 
join @tableB b
  on a.EX = b.EX 
 and (   (a.STATUS = b.STATUS and a.DLV = b.DLV) 
      or (a.STATUS is null)
     )
order by a.EX, a.STATUS, a.DLV;

Wenn Sie mit '' leben können, wird dies einfach

declare @tableA table (EX char(1) not null, STATUS char(3), DLV varchar(10), Actual_FEE decimal(18,2)
                       primary key (ex, status, dlv));
insert into @tableA values
('N', 'ACT', 'MAIL',   1.25),
('N', 'ACT', 'EMAIL',  1.25),
('N', 'ACT', 'PICKUP', 0),
('N', 'NON', 'MAIL',   0),
('N', 'NON', 'EMAIL',  1.25),
('N', 'NON', 'PICKUP', 0),
('Y', '',    '',       0); 

declare @tableB table (EX char(1) not null, STATUS char(3), DLV varchar(10), Expected_FEE decimal(18,2)
                       primary key (ex, status, dlv));
insert into @tableB values
('N', 'ACT', 'MAIL',   1.25),
('N', 'ACT', 'EMAIL',  0),
('N', 'ACT', 'PICKUP', 0),
('N', 'NON', 'MAIL',   1.25),
('N', 'NON', 'EMAIL',  0),
('N', 'NON', 'PICKUP', 0),
('Y', '',    '',       0);

select a.EX, a.STATUS, a.DLV, a.Actual_FEE, b.Expected_FEE  
from @tableA a 
join @tableB b
  on a.EX     = b.EX 
 and a.STATUS = b.STATUS 
 and a.DLV    = b.DLV
order by a.EX, a.STATUS, a.DLV;
1
paparazzo