"Christmas - the time to fix the computers of your loved ones" « Lord Wyrm

SQL Join Problem

Umlüx 03.09.2019 - 11:20 3792 20
Posts

Umlüx

Huge Metal Fan
Avatar
Registered: Jun 2001
Location: Kärnten
Posts: 8900
folgendes problem, ich sitze momentan komplett auf der leitung..

Ich habe zwei tabellen in einer Oracle DB

Code:
Tabelle 1
---------
1   Test1
2   Test2
3   Test3
4   Test4

Tabelle 2
---------
Test1   A
Test2   B
Test3   A
Test3   B
Test4   B
Test4   C

die beiden möchte ich nun so joinen, dass er mir immer den wert "A" ausgibt wenn dieser in Tabelle 2 vorkommt, und sonst die spalte leer oder null lässt. mein hauptproblem momentan dabei: im falle von "Test3" darf dann auch nur ein result mit "A" zurückkommen, bei "Test4" nur eine mit leer/null.

ich hoffe ich habe das halbwegs verständlich ausgedrückt.. :D

DANKE!

berndy2001

Komasäufer
Avatar
Registered: Feb 2003
Location: Vienna
Posts: 1949
Quick und Dirty fällt mir ein Subquerie mit where spalte2 = 'A' ein

Umlüx

Huge Metal Fan
Avatar
Registered: Jun 2001
Location: Kärnten
Posts: 8900
hatte ich schonmal, aber dann fehlen mir die spalte != A komplett.
oder ich bin zu deppat...

meepmeep

Here to stay
Avatar
Registered: Feb 2006
Location: Wien
Posts: 2330
so eventuell?

Code: SQL
select t1.name, t2.category from table1 t1 left outer join table2 t2 on (t2.name = t1.name AND t2.category = 'A');
Bearbeitet von meepmeep am 03.09.2019, 11:36

Umlüx

Huge Metal Fan
Avatar
Registered: Jun 2001
Location: Kärnten
Posts: 8900
selbiges ergebnis. war mein erster gedanke (vom MySQL her, aber eventuell funktioniert Oracle hier anders?),aber die != A fehlen dann komplett.

im prinzip solls am ende so aussehen:
Code:
1   Test1   A   
2   Test2
3   Test3   A
4   Test4

meepmeep

Here to stay
Avatar
Registered: Feb 2006
Location: Wien
Posts: 2330
das tut es bei mir. Es ist halt wichtig, dass es left outer join ist. Das sorgt dafür, dass das ergebnis auch die Inhalte der Linken Seite enthält, wenn das join kriterium nicht aufgeht.

Code: SQL
create table table1 (
    name varchar2(50)
);
--drop table table1;

create table table2 (
    name varchar2(50),
    category varchar2(50)
);
--drop table table2;

insert into table1 values ('test1');
insert into table1 values ('test2');
insert into table1 values ('test3');
insert into table1 values ('test4');

insert into table2 values ('test1', 'A');
insert into table2 values ('test2', 'B');
insert into table2 values ('test3', 'A');
insert into table2 values ('test3', 'B');
insert into table2 values ('test4', 'B');
insert into table2 values ('test4', 'C');

select t1.name, t2.category from table1 t1 left outer join table2 t2 on (t2.name = t1.name AND t2.category = 'A');
Code:
output:
test2	
test4	
test3	A
test1	A
Bearbeitet von meepmeep am 03.09.2019, 11:50

Umlüx

Huge Metal Fan
Avatar
Registered: Jun 2001
Location: Kärnten
Posts: 8900
interessant. ich bekomme
Code:
1   Test1   A   
3   Test3   A

JDK

Oberwortwart
Avatar
Registered: Feb 2007
Location: /etc/graz
Posts: 2742
Wenn du als Ergebnis eh nur eine Spalte aus T2 haben willst, warum dann ein Join?

Code: SQL
SELECT CASE WHEN C2 = 'A' THEN C2 ELSE NULL END AS Result FROM T2;
Gibt dir eine Liste mit allen Einträgen der zweiten Spalte (C2) aus der zweiten Tabelle (T2), wobei alle Ergebnisse != 'A' genulled werden.
Wenn C1 noch dazu soll:
Code: SQL
SELECT C1, CASE WHEN C2 = 'A' THEN C2 ELSE NULL END AS Result FROM T2;

Oder willst du die Einträge aus T1 doch haben? Dann sollte meepmeeps Query eh passen.
Wenn es nicht das gewünschte Ergebnis liefert, kannst du ein RIGHT JOIN machen (du willst ja alle Einträge aus T2 haben) und alle T2.C2 != 'A' wieder mit dem CASE abändern.
Bearbeitet von JDK am 03.09.2019, 12:05

Umlüx

Huge Metal Fan
Avatar
Registered: Jun 2001
Location: Kärnten
Posts: 8900
ja ich will die aus T1 auch haben.
Mit meeps query bekomm ich aber nur noch die "A" einträge zurück, mit deinem dafür alle. Test3 und Test4 sind dann doppelt drin. einmal mit A und einmal Null.

meepmeep

Here to stay
Avatar
Registered: Feb 2006
Location: Wien
Posts: 2330
Und du bist dir sicher, dass du einen left outer join machst?
Kannst du deine query mal posten?

JDK

Oberwortwart
Avatar
Registered: Feb 2007
Location: /etc/graz
Posts: 2742
Ah okay, ich glaub jetzt versteh ich, was du willst.

meepmeeps Query sollte dann passen (vlt noch SELECT DISTINCT, falls du mehrere Einträge mit T2.C2 = A pro Test hast).

Umlüx

Huge Metal Fan
Avatar
Registered: Jun 2001
Location: Kärnten
Posts: 8900
Code: SQL
SELECT DISTINCT B.BOOKINGNUMBER, B.TRAVELSTARTDATE,  BPB.BUSINESSPARTNERNUMBER, BN.DEFAULTDESCRIPTION 

FROM BOOKING B
LEFT JOIN TOP_SPR_PROD.BUSINESSPARTNERBASE BPB ON B.PAYINGBP_ID = BPB.ID
LEFT JOIN BOOKINGSERVICE BS ON BS.BOOKING_ID = B.ID
LEFT OUTER JOIN TOP_SPR_PROD.BOOKINGNOTE BN ON BN.BOOKINGSERVICE_ID = BS.ID  AND BN.DEFAULTDESCRIPTION LIKE '*BN%'

WHERE BPB.BUSINESSPARTNERNUMBER = '123' 
AND BN.NOTETYPE_ID = '81'

ORDER BY B.BOOKINGNUMBER

knackpunkt ist BN.DEFAULTDESCRIPTION, das sind notizen zur buchung. und es kann mehrere notizen pro buchung geben.
er solls ausschreiben, wenn es einen eintrag gibt der mit '*BN' beginnt (und die restlichen ignorieren). oder eben leer lassen, wenn kein solcher vorkommt.

meepmeep

Here to stay
Avatar
Registered: Feb 2006
Location: Wien
Posts: 2330
ohne dem join auf BOOKINGNOTE (also die Zeile komplett weg) enthält das Ergebnis die erwarteten Inhalte aus BOOKING?
'*BN%' matched auch sicher die gesuchten Inhalte aus BN.DEFAULTDESCRIPTION?

berndy2001

Komasäufer
Avatar
Registered: Feb 2003
Location: Vienna
Posts: 1949
Zitat aus einem Post von Umlüx
hatte ich schonmal, aber dann fehlen mir die spalte != A komplett.
oder ich bin zu deppat...

so hätt ich gmeint:
Code: SQL
with tab1 as (
select decode(rownum, 1, 1, 2, 2, 3, 3, 4, 4) as id,
       decode(rownum, 1, 'Test1', 2, 'Test2', 3, 'Test3', 4, 'Test4') as wert
  from dual
connect by level <= 4
),
tab2 as (
select decode(rownum, 1, 'Test1', 2, 'Test2', 3, 'Test3', 4, 'Test3', 5, 'Test4', 6, 'Test4') as wert,
       decode(rownum, 1, 'A', 2, 'B', 3, 'A', 4, 'B', 5, 'B', 6, 'C') as result
  from dual
connect by level <= 6)

select tab1.*, (select result from tab2 where tab2.wert = tab1.wert and tab2.result = 'A') from tab1;
oder
Code: SQL
select tab1.*, tab2.* from tab1 left join tab2 on (tab2.wert = tab1.wert and tab2.result = 'A')

2019-09-03-13_14_51-oracle-sql-developer_239856.png
Bearbeitet von berndy2001 am 03.09.2019, 13:23

Umlüx

Huge Metal Fan
Avatar
Registered: Jun 2001
Location: Kärnten
Posts: 8900
lass ich das "AND BN.DEFAULTDESCRIPTION LIKE '*BN%'" einfach weg, erhalte ich alle daten, ja.
halt teilweise doppelt und dreifach, da es wie gesagt zu jeder BOOKINGNUMBER mehrere unterschiedliche BOOKINGNOTES geben kann.

mit dem AND.. bekomme ich nur noch die "*BN%"

aktuell spiele ich mich gerade mit LISTAGG herum um. idee wäre die Notes einfach zu kombinieren und dann auf den suchstring zu prüfen.
Kontakt | Unser Forum | Über overclockers.at | Impressum | Datenschutz