Datenbankabfrage mit or Klausel

motto1234

Benutzer
Beiträge
6
Hallo an alle,

ich fange gerade erst mit Datenbankabfragen und komme einfach nicht weiter.
Ich habe ein Buchhaltungsprogramm (GS-Auftrag) was seine Daten in einer MySQL Datenbank speichert. Auf diese Datenbank kann nur lesend zugegriffen werden.
Ich muss eine Abfrage erstellen damit Weihnachtspost verschickt werden kann.

Ich habe schon einiges hinbekommen aber eben noch nicht alles :-((
In meiner WHERE Klausel ist eine OR Anweisung die einfach nicht will. Wenn ich die OR Klausel weglasse kommen die Ergebnisse. Ist die OR -Klausel vorhanden läuft die Abfrage ca. 15 Minuten und bricht dann mit dem Fehler out of memory ab.

Ich hoffe das mir geholfen werden kann.

Die aktuelle Abfrage sieht so aus

SELECT DISTINCT
sg_adressen.Post1,
sg_adressen.Post2,
sg_adressen.Post3,
sg_adressen.Post4,
sg_adressen.Post5,
sg_adressen.Post6,
sg_auf_fschrift.ERFART,
sg_auf_fschrift.ENDPRB,
sg_auf_fschrift.DATUM,
sg_adr_bemerkung.Bemerkung,
sg_adressen.Suchbegriff
FROM
sg_adressen ,
sg_adr_bemerkung,
sg_auf_fschrift
WHERE
sg_adr_bemerkung.Bemerkung = "weih15"
or (
sg_adressen.SG_Adressen_PK = sg_adr_bemerkung.SG_Adressen_FK AND
sg_adressen.SG_Adressen_PK = sg_adr_bemerkung.SG_Adressen_FK AND
sg_adressen.SG_Adressen_PK = sg_auf_fschrift.SG_ADRESSEN_FK AND
sg_auf_fschrift.ENDPRB >= "790" AND
sg_auf_fschrift.DATUM LIKE "2015%" AND
sg_auf_fschrift.ERFART = "04RE"
)

Vielen Dank für eure Hilfe
 
Werbung:
Schwer zu erraten was Du erreichen willst. Aber das, was Du im OR (....) stehen hast sieht (zum Teil, die ersten 3 Zeilen) eher nach Join-Condition aus. Stelle die Abfrage auf sauber Join-Syntax um, das könnte helfen.
 
Vielen Dank für die Antwort,

Leider bin ich totaler Anfänger was Datenbanken betrifft. Die Sache mit dem Join habe ich noch nicht verstanden.
Ich versuche mal die Aufgabe zu erläutern.
Es gibt in der Datenbank 179 Tabellen. In drei von den Tabellen stehen Daten, die ich brauche.
1. Tabelle sg_adressen stehen die Adressdaten von allen Kunden.
2. Tabelle sg_auf_fschrift stehen die Daten von Rechnungen, Angeboten .......
3. Tabelle sg_adr_bemerkung steht in der Spalte Bemerkung, ob der Kunde egal welcher Umsatz und Letztkontakt er hatte trotzdem Weihnachtspost bekommen soll.

Aufgabe:
Es sollen alle Kundenadressen gefunden werden die
1. eine Rechnung größer 790 Euro haben und
2. eine Rechnung im Jahr 2015 erhalten hatten
3. oder die Information in der 3. Tabelle steht das sie Weihnachtspost bekommen sollen
 
Vereinfacht:

Code:
test=*# create table kunden (id int primary key, name text);   
CREATE TABLE   
test=*# create table rechnung (kunde int references kunden, datum date, betrag int);
CREATE TABLE   
test=*# create table kunden_info (kunde int references kunden, brief bool);
CREATE TABLE   
test=*# copy kunden from stdin;   
Enter data to be copied followed by a newline.   
End with a backslash and a period on a line by itself.   
>> 1  kunde1
>> 2  kunde2
>> \.
COPY 2
test=*# insert into rechnung values (1, '2015-01-01', 20);
INSERT 0 1
test=*# insert into rechnung values (2, '2014-01-01', 2000);
INSERT 0 1
test=*# insert into kunden_info values (1, true);
INSERT 0 1
test=*# insert into kunden_info values (2, true);
INSERT 0 1

Du hast nun:

Code:
test=*# select * from kunden;
 id |  name
----+--------
  1 | kunde1
  2 | kunde2
(2 rows)

test=*# select * from rechnung ;
 kunde |  datum  | betrag
-------+------------+--------
  1 | 2015-01-01 |  20
  2 | 2014-01-01 |  2000
(2 rows)

test=*# select * from kunden_info ;
 kunde | brief
-------+-------
  1 | t
  2 | t
(2 rows)

Wir fragen ab:

Code:
test=*# select k.id from kunden k left join rechnung r on k.id=r.kunde where extract('year' from datum) = 2015 or betrag > 10000;
 id   
----   
  1   
(1 row)   

test=*# select k.id from kunden k left join rechnung r on k.id=r.kunde where extract('year' from datum) = 2015 or betrag > 1000;
 id
----
  1
  2
(2 rows)

test=*# select k.id from kunden k left join rechnung r on k.id=r.kunde left join kunden_info ki on k.id=ki.kunde where extract('year' from datum) = 2015 or betrag > 10000 or ki.brief;
 id
----
  1
  2
(2 rows)

test=*# select k.id from kunden k left join rechnung r on k.id=r.kunde left join kunden_info ki on k.id=ki.kunde where extract('year' from datum) = 2015 or betrag > 10000 or ki.brief;
 id
----
  1
  2
(2 rows)

Versuch es zu verstehen, ist ganz simpel.
 
so ich bins noch mal ;-(
folgende Abfrage habe ich mit Hilfe von akretschmer zusammengebastelt :)

select distinct
a.Post1,
a.Post2,
a.Post3,
a.Post4,
a.Post5,
a.Post6,
a.Post7
from
sg_adressen a
left join
sg_auf_fschrift f on
a.SG_Adressen_PK=f.SG_ADRESSEN_FK
left join
sg_adr_bemerkung b on
a.SG_Adressen_PK=f.SG_ADRESSEN_FK
where
extract(year from DATUM) = 2015
or
ENDPRB >= "790"
or
ERFART = "04RE"

Nach 6 Minuten Abfragezeit habe ich die Sache erst einmal abgebrochen. Zum Testen nutze ich Navicut und den Query Editor.
Gibt es noch Rettung für mich??
 
Ich habe vor die Abfrage mal ein Explain vor SELECT gesetzt und "extract(year from DATUM) = 2015" durch "f.DATUM LIKE "2015%"" ersetzt.
Die Abfrage mit LIKE hatte schon mal Ergebnisse geliefert. Die Ausgabe mit EXPLAIN sieht so auf

1 SIMPLE a ALL 7629 Using temporary
1 SIMPLE f ref sg_auf_fschrift11 sg_auf_fschrift11 5 mand5.a.SG_Adressen_PK 1 Distinct
1 SIMPLE b ALL 7638 Using where; Distinct
 
ja, offenbar fehlen passende Indexe. Das MySQL-Explain ist halt wie MySQL selbst: grottig. Funktionale Indexe kann es nicht (für die erste Where-Condition sinnvoll). Using temporary ist halt auch von der Performance nicht prall.
 
Werbung:
Statt f sollte es b heißen:

select distinct
a.Post1,
a.Post2,
a.Post3,
a.Post4,
a.Post5,
a.Post6,
a.Post7
from
sg_adressen a
left join
sg_auf_fschrift f on
a.SG_Adressen_PK=f.SG_ADRESSEN_FK
left join
sg_adr_bemerkung b on
a.SG_Adressen_PK=b.SG_ADRESSEN_FK
where
extract(year from DATUM) = 2015
or
ENDPRB >= "790"
or
ERFART = "04RE"
 
Zurück
Oben