PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : SQL Abfrage-Problem


CoconutKing
2012-09-17, 19:02:15
Hallo,

hab ein Problem mit SQL und brauch eure Hilfe:


2 Tabellen:

Tabelle1:

PK int ID, int TX, int RX
1,0,0
...
435, 123,124

Tabelle2:
PK int "ID", varchar "VWert"
...,...
123, ventil a
124, ventil b
...,....

Wie bekomme ich eine Abfrage hin, die über die Tabelle 1 geht und in die spalten TX,RX die Namen aus der Tabelle 2 anzieht?
Hört sich einfach an, bekomms aber nicht hin, weil entweder der Name von Tabelle1.TX auch in RX angezeigt wird oder andersrum.

Als Ergebnis erwarte ich sowas:
435 , ventil a, ventil b

Exxtreme
2012-09-17, 19:07:57
So in etwa:

select Tabelle1.ID as "ID", Tabelle2.VWert as "VWert" from Tabelle1, Tabelle2 where Tabelle1.ID = Tabelle2.ID

Edit: Jetzt kapiere ich was du willst. Moment ...

select Tabelle1.ID as "ID", Tabelle2.VWert as "VWert_TX", Tabelle2.VWert as "VWert_RX" from (Tabelle1 inner join Tabelle2 as "Tabelle2_TX" on Tabelle2_TX.ID = Tabelle1.TX) inner join Tabelle2 as "Tabelle2_RX" on Tabelle2_RX.ID = Tabelle1.ID;

CoconutKing
2012-09-17, 19:11:56
läuft wohl auf inner join usw raus.

steh aufm schlauch :mad:

Nagelbrett
2012-09-17, 19:16:42
select a.id, b.VWert, c.VWert from tabelle1 a, tabelle2 b, tabelle2 c where tx=b.id and rx=c.id;

geht das nicht?

PatkIllA
2012-09-17, 19:37:16
läuft wohl auf inner join usw raus.

steh aufm schlauch :mad:
Exxtreme hat es doch schon vorgemacht. In der Form wie du es haben willst braucht es zwei Joins. Hast du zu jedem Datensatz in Tabelle zwei auch immer zwei Datensätze passend zu TX und RX?
Oder wo genau ist das das Problem?

select a.id, b.VWert, c.VWert from tabelle1 a, tabelle2 b, tabelle2 c where tx=b.id and rx=c.id;

geht das nicht?
Im Prinzip auch ein Join.

Exxtreme
2012-09-17, 20:27:46
läuft wohl auf inner join usw raus.

steh aufm schlauch :mad:
Was ist an einem inner join jetzt schlecht? Der DB-interne Optimizer optimiert die Dinger meist eh' raus.

PatkIllA
2012-09-17, 20:30:20
Was ist an einem inner join jetzt schlecht? Der DB-interne Optimizer optimiert die Dinger meist eh' raus.
Was optimiert der raus? Er muss doch den Join machen. Erst einen kompletten CrossJoin und den nachzufiltern dürfte nicht vorkommen.

Exxtreme
2012-09-17, 20:40:47
Was optimiert der raus? Er muss doch den Join machen. Erst einen kompletten CrossJoin und den nachzufiltern dürfte nicht vorkommen.
Also zumindest der DB2-Optimizer entfernt die Joins sehr gerne und macht was Äquivalentes draus. Das sieht dann so ähnlich aus wie Nagelbretts Statement. Ja, technisch ist das immer noch ein Join aber aber das optimierte SQL-Statement hat dann selten welche.

PatkIllA
2012-09-17, 20:46:04
Was aus den Abfragen wird hängt ja sogar noch von der Zeit ab. Datenbanken optimieren das ja auch noch über die Zeit.
Wenn ich mich jetzt richtig erinnere sieht im SQL-Server Execution Plan für beide Arten von Joins das gleiche raus.

Exxtreme
2012-09-17, 21:07:26
Ja, in der DB2 sieht der Ausführungplan auch exakt gleich aus. Warum die Joins durch Äquivalente ersetzt werden weiss ich jetzt auch nicht. Gut, IBM hat schon immer anders getickt. :/

samm
2012-09-17, 23:22:43
Wenn ich mich jetzt richtig erinnere sieht im SQL-Server Execution Plan für beide Arten von Joins das gleiche raus.
Es ist auch einfach eine andere Schreibweise für das gleiche

SELECT ... FROM A, B WHERE A.id = B.id
SELECT ... FROM A INNER JOIN B ON A.id = B.id

Rausoptimieren kann das DBMS joins eigentlich nicht, ausser vielleicht in unnötig komplizierten Konstrukten, in denen mehrfach das gleiche gemacht wird, oder Joins auf einen konstanten Wert oder sowas. Es ist nur nicht immer die "anstrengendste" Art JOIN nötig (nested loop), sondern je nach Eigenschaften der Join-Attribute auch merge- oder hash-joins.

(Überlegungsfehler nicht ausgeschlossen, langer Tag heute ;))

CoconutKing
2012-09-18, 07:47:21
So in etwa:

[strike]select Tabelle1.ID as "ID", Tabelle2.VWert as "VWert" from Tabelle1, Tabelle2 where Tabelle1.ID = Tabelle2.ID[/strike


Edit: Jetzt kapiere ich was du willst. Moment ...

select Tabelle1.ID as "ID", Tabelle2.VWert as "VWert_TX", Tabelle2.VWert as "VWert_RX" from (Tabelle1 inner join Tabelle2 as "Tabelle2_TX" on Tabelle2_TX.ID = Tabelle1.TX) inner join Tabelle2 as "Tabelle2_RX" on Tabelle2_RX.ID = Tabelle1.ID;

Geht nicht. Bekomme wieder:
Id, name1, name1

Und nicht
Id, name1 , name2

Exxtreme
2012-09-18, 09:27:55
Geht nicht. Bekomme wieder:
Id, name1, name1

Und nicht
Id, name1 , name2

Versuche Folgendes:

select Tabelle1.ID as "ID", Tabelle2_TX.VWert as "VWert_TX", Tabelle2_RX.VWert as "VWert_RX" from (Tabelle1 inner join Tabelle2 as "Tabelle2_TX" on Tabelle2_TX.ID = Tabelle1.TX) inner join Tabelle2 as "Tabelle2_RX" on Tabelle2_RX.ID = Tabelle1.ID;

CoconutKing
2012-09-18, 18:22:37
thx exxtreme,

deine erste lösung hat mich nach rumdoktoren zum erfolg gebracht, in deiner Abfrage hat nur etwas vom namen her nicht gepasst.

Matrix316
2012-09-19, 08:37:21
Man kanns auch ohne Join machen:

select
a.TX,
a.RX,
(select VWert from Tabelle2 where ID = a.ID) as VWert
from Tabelle1 a

oder so. Aber der Join hat den Vorteil, dass er meistens stimmt. *g* Während Subselects manchmal komische Formen annehmen, wenn NULL Werte vorhanden sind oder beim Subselect mehrere gleiche IDs in der anderen Tabelle vorkommen gibts dann Fehler.

samm
2012-09-19, 19:11:34
Da hast du auch einen Join (where ID = a.ID). Je nach Optimizer hast du sogar einen deutlichen Nachteil mit einem solchen Konstrukt. Ausserdem würde das Problem des TS mit der Abfrage nicht gelöst, aber er hat seine Lösung ja schon ;)

Matrix316
2012-09-20, 12:23:47
Join ist was anderes. Das wäre ein Subselect. ;)

Der Unterschied ist halt auch, bei einem Join haste alle Felder aller Tabellen und du musst Selektieren. Bei einem Subselect kannste auch select * von einer Tabelle machen und zusätzlich die anderen Felder hinzuselektieren ohne alle Felder von Hand auswählen zu müssen. :)

Wobei ein Join meistens wirklich schneller ist, aber es gibt auch Ausnahmen.

samm
2012-09-20, 20:18:58
So, nachdem ich als Gast nach 3 key-kaptcha Reloads aufgegeben habe, nun von zuhause aus^^

Ok, correlated subselect, zugegeben, ich hatte vorgegriffen: Diesen subselect hätte man besser als entsprechenden Join geschrieben, weil als correlated subselect in dieser Form für jedes Resultattupel aus Tabelle1 die Tabelle2 neu abgefragt werden muss. Mit einem simplen Join hätte das System wesentlich geringeren Aufwand: Join-Attribut ist ein Key --> einmal mergen, und eins nach dem andern durchgehen vs. eins nach dem andern durchgehen und für jedes die zweite Tabelle laden und zu selektieren. Aber wie gesagt, je nach Optimizer wird das vielleicht erkannt und angepasst, muss ich mal im Büro testen...
Der Unterschied ist halt auch, bei einem Join haste alle Felder aller Tabellen und du musst Selektieren. Bei einem Subselect kannste auch select * von einer Tabelle machen und zusätzlich die anderen Felder hinzuselektieren ohne alle Felder von Hand auswählen zu müssen.:)Selektieren? Meinst du projezieren? Ich sehe jetzt nicht, was an

SELECT a.*, b.feld1 FROM a, b WHERE a.id = b.id

aufwändiger zu schreiben, zu verstehen oder auszuführen sein soll als an

SELECT *, (SELECT feld1 FROM b WHERE id = a.id) FROM a

Ganz im Gegenteil ist die erste Variante einfacher in jedem Sinne. Oder sprechen wir aneinander vorbei? :)

Matrix316
2012-09-21, 10:19:52
[...]
Selektieren? Meinst du projezieren? Ich sehe jetzt nicht, was an

SELECT a.*, b.feld1 FROM a, b WHERE a.id = b.id

aufwändiger zu schreiben, zu verstehen oder auszuführen sein soll als an

SELECT *, (SELECT feld1 FROM b WHERE id = a.id) FROM a

Ganz im Gegenteil ist die erste Variante einfacher in jedem Sinne. Oder sprechen wir aneinander vorbei? :)

Da gibts bestimmt interne Unterschiede, weil du ja beim Subselect nur auf ein Feld von b zugreifst, während bei from a,b oder from a inner jon b intern ja beide Tabellen komplett "Kreuzt" und dann erst selektiert wird... oder so. (alles nur Spekulation von mir ;D))

Allerdings arbeite ich zwar seit 5 Jahren mit SQL, aber auf "a.*" beim Join bin ich ehrlich gesagt noch nicht gekommen...:redface:

Der Subselect hat aber z.B: Vorteile, wenn du für einen Datensatz aus der einen Tabelle auch nur einen insgesamt haben willst, weil du dann auch mit Select Top 1 oder Select Max etc. nur einen Wert auswählen kannst, während mit join kriegste x*y Zeilen. Natürlich kommts immer drauf an, was du am Ende haben willst.

Beispiel:

Tabelle 1
A B
1 a

Tabelle 2
A B C
1 1 10
2 1 11

Ein Join (select * from Tabelle1 inner join Tabelle2 on Tabelle1.A =Tabelle2.B) gibt
A B A B C
1 a 1 1 10
1 a 2 1 11

mit Subselect auf max C aus Tabelle 2 kannste dann sowas machen.

A B A B C
1 a 2 1 11

samm
2012-09-21, 22:44:07
Ich ja will subselects auch nicht verteufeln, und es gibt immer Orte, wo sie Sinn machen. Bloss wenn sie correlated sind und letztlich das gleiche rauskommt wie bei einem bequemen Join, dann wage ich die generelle Aussage ;) Sonst ist halt so, manchmal führt nur das eine oder das andere, meist gibt es mehrere Wege zum Ziel. Wenn es um grosse Datenmengen, Antwortzeiten und/oder Locking-Verhalten geht, lohnt es sich, den Ausführplan anzusehen und zudem zu benchmarken wenn möglich. Aber irgendwie sind das grad Plattitüden^^ Sry.
Allerdings arbeite ich zwar seit 5 Jahren mit SQL, aber auf "a.*" beim Join bin ich ehrlich gesagt noch nicht gekommen...:redface:Ist doch schön, wie man nie ausgelernt hat, drum mag ich z.B. meinen Job auch :)

Berni
2012-09-23, 15:55:12
Was nun schneller ist hänge von vielen Faktoren ab: Datenmengen, Indexen, Datenbanksystem etc.
Beim Subselect wird meist diese Subselect-Abfrage pro Ergebnissatz einmal ausgeführt (also ein Lookup pro Satz). Wenn es keinen Index gibt oder man viele Sätze ausgibt kann das horrende Laufzeiten ergeben. Bei einem Join dagegen können z.B. HashJoins verwendet werden was dann auch bei mehreren Millionen Sätzen noch recht fix geht (es dauert dann zwar länger bis man den ersten Satz kriegt aber die Gesamtdauer fürs Abholen aller Sätze ist viel niedriger).