Zwei Queries verbinden

Hey :smile:

ich möchte gerne zwei Queries verbinden, aber kommt einfach nicht weiter.

Ich habe folgende Daten
start & dringend (das sind Aufträge die den Status „dringend“ haben)

Ich hätte gerne
„Start“; „Anzahl“; „Anteil %“ ; „Anzahl dringende Aufträge“
Köln; 20 ; 0,2 ; 9
Berlin; 40 ; 0,4 ; 35
München; 40 ; 0,4 ; 2

Für die ersten drei Spalten benutz ich meine erste Query; für die letze meine zweite Query.

  1. Query
    SELECT
    t1.start, countt1.start) as anzahl, round(ratio_to_report(count(t1.start)) over (), 4)*100 as percentage
    FROM
    t1, t21
    WHERE
    t1.id=t2.id
    GROUP BY
    t1.start
    ORDER BY
    t1.start ASC

  2. Query
    SELECT
    t1.start, count(t1.start)
    FROM
    t1, t2
    WHERE t1.id = t2.id
    and t1.dringend=1
    GROUP BY
    t1.start
    ORDER BY
    t1.start ASC

Wichtig ist, dass ich jeweils die dringenden Aufträge von allen Aufträgen, die ab Start(i) losgefahren sind auch dem enstsprechend anzeigen kann.

Dies war meine Lösung -
die aber nicht funktioniert => da krieg ich nämlich folgendes:
Start ; Anzahl ; Anteil%; dringende Aufträge
Köln ; 20 ; 0,2 ;46
Berlin ; 40 ; 0,4 ; 46
München ; 40; 0,4 ; 46
(46 = 9+35+2)

SELECT
t1.start, count(t1.start) as anzahl,
round(ratio_to_report (count(t1.start)) over (),4)*100 as percentage,

(SELECT count(t1.start)
FROM t1, t2
WHERE t1.id=t2.id AND t1.dringend=1)

FROM
t1, t2
WHERE
t1.id=t2.id
GROUP BY
t1.start
ORDER BY
t1.start ASC

t1.start ist ein string
t1.dringend ist entweder 1 oder 0
Ich benutze Oracle 8i (ich glaub 8.1.7).

Hat jemand eine Idee wie ich die beiden Queries verbinden kann?

Vielen Dank & herzliche Grüße

Hallo,

aus Deinen Beispielen werde ich nicht ganz schlau, aber ich glaube Du könntest mal folgende Struktur probieren:

Select a.key, a.wert1, a. …, b.wert1, b…
from
(select key, … from TabelleA) a
, (select key, … from TabelleB) b
where a.key = b.key

in den Klammern kannst Du beliebig komplexe queries schreiben (da können sogar nochmal sub-selects drin sein…)

Viele Grüße
Lumpi

Hi Lumpi,

Select a.key, a.wert1, a. ..., b.wert1, b...
from
 (select key, ... from TabelleA) a
, (select key, ... from TabelleB) b
where a.key = b.key

Sieht aber ganz böse nach viel zu vielen Zwischenschritten für die Datenbank aus… Lieber mit einem geeignet Key und einem Join, wenn nicht möglich, dann evtl. noch ein Kreuzjoin den die Datenbank selbst noch optimieren kann:

SELECT 
 a.key, a.wert1, a. ..., b.wert1, b. ...
FROM
 table\_a AS a
INNER JOIN
 table\_b AS b ON b.foreign\_key = a.key

oder mit Kreuzprodukt

SELECT
 a.key, a.wert1, a. ..., b.wert1, b. ...
FROM
 table\_a AS a, table\_b AS b
WHERE
 a.key = b.foreign\_key

Grüße
m4tt3n

Hi!

Sieht aber ganz böse nach viel zu vielen Zwischenschritten für
die Datenbank aus…

Kommt auf die Datenbank an und wie sie mit Views (etwas anderes sind die Sub-Selects ja nicht) umgeht … unter Oracle kein Problem, die Ergebnisse der Sub-Selects werden gecached und sind so für das ganze Statement sofort abrufbar - wenn das Ganze dann noch parallelisiert wird, wird’s sogar noch schneller …

Und jetzt hätte ich mal eine Frage:

FROM
table_a AS a
INNER JOIN
table_b AS b ON b.foreign_key = a.key

FROM
table_a AS a, table_b AS b
WHERE
a.key = b.foreign_key

Wo ist da der Unterschied? Da ich INNER, OUTER, LEFT, RIGHT usw. (einzige Ausnahme: FULL OUTER JOIN) nie verwende, war ich stets der Meinung, dass diese beiden Bedingungen eigentlich ident sind (vom Ergebnis zumindest - wie das Parsen abläuft und die Zugriffspläne errenet werden bzw. aussehen mal außer Acht gelassen)?

Grüße,
Tomh

PS: Oder ist es nur noch zu früh am morgen …

Hey :smile:

vielen Dank für eure Antworten…aber ich hab mich wohl schlecht erklärt.

Ich habe eine (ewig große) Tabelle über Transporte mit einem LKW. Nun soll ich sagen wie viele LKWs von einem bestimmten Punkt aus gestartet sind (und viel Prozent dies vom gesamten ist) und wie viele dieser gestarteten LKWs mit dem Status „besonders dringend“ versehen sind.

z.B. 25 LKWs fahren in Köln los, aber nur 9 sind davon als „dringend“ markiert.

Um die Anzahl der LKWs, die in Köln starten, abzufragen (und den prozentualen Anteil => das ist aber im Moment eher unwichtig) benutze ich meine 1. Query.

Um die Anzahl der LKWs, die in Köln gestartet sind und dringend sind zu berechnen benutze ich die 2. Query. Ein LKW kann entweder dringend (dringend=1) oder nicht dringend (dringend=0) sein.

Das Problem ist, dass ich ja verschieden Orte habe (z.B. Köln, Berlin, München) und jeweils pro Ort die Anzahl der LKWs und dann noch einmal wie viele von diesen „dringend“ sind wissen möchte.

Hmm…ich hoffe ich habe jetzt meine „Bespiele“ vom ersten Post besser beschrieben.

Um die Anzahl der LKWs eines bestimmten Ortes zu finden, habe ich meine Tabelle (t1) einfach kopiert (t2), weil ein self-join zu lange dauert bei dieser riesen Tabelle.

Bei euren Vorschlägen hab ich gar nicht gefunden, wie ich die Anzahl (normal & dringend) bestimmen kann. „Dringend“ ist ja die ganz normale Abfrage (1. Query) nur mit dem Zusatz, dass „dringend“ entweder 1 oder 0 sein kann.

Würd mich freuen, wenn ihr mir weiter helfen könnt :smile:

Lieben Dank & viele Grüße

Hallo ITGirl,

du kannst 2 Abfragen mit dem Schlüsselwort UNION verbinden.

Wenn du die anzahl aller LKWS habenw willst in dringend und nicht dringend aufgeteilt müsstest du das Schlüsselwort GROUP BY verwenden.
Beispiel:

*hoffe ich hab dich richtig verstanden*
viel erfolg weiterhin.

Hi ITGirl,

Oracle 8 - das tut mir aber leid. Ich habe mal auf die Schnelle folgende Lösung gebastelt (Oracle 10R2):

CREATE TABLE LKW
(
 VON VARCHAR2(10 BYTE) NOT NULL,
 DRINGEND INTEGER NOT NULL
);

Insert into LKW (VON, DRINGEND) Values ('wien', 0);
Insert into LKW (VON, DRINGEND) Values ('wien', 0);
Insert into LKW (VON, DRINGEND) Values ('stuttgart', 1);
Insert into LKW (VON, DRINGEND) Values ('berlin', 1);
Insert into LKW (VON, DRINGEND) Values ('berlin', 0);
Insert into LKW (VON, DRINGEND) Values ('berlin', 0);
Insert into LKW (VON, DRINGEND) Values ('berlin', 0);
Insert into LKW (VON, DRINGEND) Values ('muenchen', 1);
Insert into LKW (VON, DRINGEND) Values ('muenchen', 0);
Insert into LKW (VON, DRINGEND) Values ('koeln', 1);
Insert into LKW (VON, DRINGEND) Values ('koeln', 0);
Insert into LKW (VON, DRINGEND) Values ('koeln', 0);
COMMIT;

Meine Abfrage

with
 cnt\_von
 as
 (
 select 
 von, 
 count(von) cnt
 from
 lkw
 group by 
 von
 ),
 cnt\_drg
 as
 (
 select 
 von, 
 sum(dringend) cnt
 from
 lkw
 group by 
 von
 ),
 cnt\_total
 as
 (
 select 
 count(1) cnt 
 from
 lkw
 )
select
 cnt\_von.von "Start"
 ,cnt\_von.cnt "Anzahl"
 ,100\*cnt\_von.cnt/cnt\_total.cnt "%"
 ,cnt\_drg.cnt "Abzahl dringend"
from 
 cnt\_von
 ,cnt\_drg
 ,cnt\_total
where
 cnt\_von.von = cnt\_drg.von
order by
 1;

liefert dann das hoffentlich Gewünschte:

Start Anzahl % Abzahl dringend
---------- ---------- ---------- ---------------
berlin 4 33,3333333 1
koeln 3 25 1
muenchen 2 16,6666667 1
stuttgart 1 8,33333333 1
wien 2 16,6666667 0

5 rows selected. 

Lieber keine Monstertabelle duplizieren, das macht die Sache bestimmt nicht schneller.

gruss
bernhard

Hallo ITGirl,
Hallo Bernhard,

Die Abfrage sollte mit

select von "Start",
 count(\*) "Anzahl",
 sum(decode(dringend,1,1,0)) "Abzahl dringend",
 sum(decode(dringend,1,1,0))/count(\*) "%"
 from lkw
;

etwas schneller und kürzer formuliert sein. Die "Entscheidungs"funktion decode (wenn 1. Wert = 2. Wert, dann 3. Wert sonst 4. Wert) gibt es unter anderen Namen auch in anderen Dialekten.

MfG Georg V.

Hi Georg,
die Ausgabe sollte aber doch nach Städten bzw. Startorten gruppiert sein, daher ist die

GROUP BY

Klausel wohl nicht wegzulassen.

gruss & schönes WE
bernhard

Hallo Bernhard,

ja kommt davon, wenn es nicht testet sondern aus dem Bauch tippt. Das Statement hätte so nicht funktioniert.

select von "Start",
 count(\*) "Anzahl",
 sum(decode(dringend,1,1,0)) "Abzahl dringend",
 sum(decode(dringend,1,1,0))/count(\*) "%"
 from lkw
 group by von
;

MfG Georg V.

Das ganze in einer Tabelle (ohne Kopie)
Hallo ITGirl,

wenn ich Dein Problem richtig verstanden habe, hätte ich hier folgende Lösung. Hierbei kannst Du auch auf die Kopie der Tabelle verzichten.

Select Startort
, count( Startort ) as Anzahl\_LKWS
, round(ratio\_to\_report(count(Startort)) over (), 4)\*100 as Anteil\_Gesamt
, sum( dringend ) as Anzahl\_Dringende\_LKWS
, sum( dringend ) / count( Startort ) as Anteil\_Dringende\_LKWS
from LKW\_BEWEGUNGEN
group by Startort;

Da der Schlüssel für die „Dringlichkeit“ geschickt durch 0 und 1 repräsentiert wird, kann hier einfach eine Summe gezogen werden.
Versuchs einfach mal.

Schöne Grüße vom
Kleines-SQL-Wunder

Hi Tomh,

Kommt auf die Datenbank an und wie sie mit Views (etwas
anderes sind die Sub-Selects ja nicht) umgeht … unter Oracle
kein Problem, die Ergebnisse der Sub-Selects werden gecached
und sind so für das ganze Statement sofort abrufbar - wenn das
Ganze dann noch parallelisiert wird, wird’s sogar noch
schneller …

Hmm, mag sein… Ich kenn mich nur mit DB2 und MS-SQL aus.
Das die Ergebnisse gecacht werden, ist auch unter DB2 so. Jedoch kann die Datenbank vorher keine Einschränkungen auf die auszuwählenden Seiten anwenden und muss bei riesigen Tabellen auch riesige Datenmengen wuchten, nur um später den größten Teil wieder aus der Ergebnisliste zu streichen.

Und jetzt hätte ich mal eine Frage:

FROM
table_a AS a
INNER JOIN
table_b AS b ON b.foreign_key = a.key

FROM
table_a AS a, table_b AS b
WHERE
a.key = b.foreign_key

Wo ist da der Unterschied? Da ich INNER, OUTER, LEFT, RIGHT
usw. (einzige Ausnahme: FULL OUTER JOIN) nie verwende,
war ich stets der Meinung, dass diese beiden Bedingungen
eigentlich ident sind (vom Ergebnis zumindest - wie das Parsen
abläuft und die Zugriffspläne errenet werden bzw. aussehen mal
außer Acht gelassen)?

Ich vermute, Du willst keine Erklärung zu INNER/OUTER/LEFT/RIGHT Join ^^
Zwischen dem obigen Kreuzprodukt und dem INNER JOIN gibt es quasi nur einen riesigen Unterschied - die Zugriffspläne. Bei MS-SQL macht sich zwischen beiden tatsächlich (solange die Tabellen sehr große Datenmengen aufweisen) einen echten Unterschied bezüglich der Performance, DB2 hingegen erweitert den Kreuzjoin mit Bedingung als impliziten INNER JOIN.

Grüße
m4tt3n

Hey :smile:

vielen lieben Dank für all eure Antworten. Einige waren ganz schön kompliziert (zumindest für mich), aber dann hab ich’s doch verstanden.

Gelöst habe ich das Ganze allerdings anders:

SELECT
t1.start,
COUNT(t1.start) as Anzahl,
COUNT(DECODE(t1.dringend, 1, 1)) as Dringend,
ROUND (RATIO_TO_REPORT (COUNT(t1.start)) OVER (), 4)*100 as Prozent

FROM t1, t2

WHERE t1.id = t2.id
GROUP BY t1.start
ORDER BY t1.start ASC

Liebe Grüße :smile: