Autor Beitrag
motion
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 295

XP, Linux
D7 Prof
BeitragVerfasst: Fr 10.08.07 13:07 
Ich muß in einem Select auf die Tabelle LAGERKARTE alle Karten ermitteln, die
-aktuell einen Bestand <=0
oder
-wo der Bestand unterhalb der Mindestmenge liegt.
Der SQL (a) dafür:
ausblenden SQL-Anweisung
1:
2:
3:
SELECT * FROM LAGERKARTE
WHERE (LAGERORT BETWEEN '00-000-00'  AND '99-999-99') AND ((BESTAND<=0) or
(BESTAND<LAGERKARTE.MINDESTMENGE)) and (KEINLAGERTEIL=0)

Ist okay und läuft auch sauschnell durch (ca. 1,5s, ca 5000 Rows).

Jetzt muss ich obige Menge weiter eingrenzen, in dem ich die Artikelhistorie untersuche (nur der obigen Lagerkarten): Nur wenn in einem angebenen Zeitraum bestimmte Buchungen vorgefallen sind, welche den Bestand<=0 gesetzt haben, soll die obige Lagerkarte angezeigt werden. Der SQL (b) dafür:
ausblenden SQL-Anweisung
1:
2:
3:
4:
5:
6:
SELECT ref0 FROM artikelhistorie
WHERE artikelhistorie.zeitstempel between '1.1.2007' and '1.9.2007'
and artikelhistorie.buchungstyp in (4,5,7,8,9,12,14,16)
and artikelhistorie.mengenaenderung is not Null
and artikelhistorie.mengenachaenderung<=0
group by artikelhistorie.ref0

Ist ebenfalls klar und läuft sauschnell durch (<1s; 114 Sätze).
Soooo, jetzt die Kombination macht mir sorgen
Ach ja: SQL b.ref0 ist der FK auf den PK von SQL a.ref


Ich habe es schon mit Join und Sub-Select ausprobiert, aber die Ausführungszeit beträgt dann jeweils 60 bis 90 Sekunden, in der der SQL Server auf Anschlag läuft und andere Stationen massive Zugriffsprobleme (=Wartezeit) bekommen. Indexprobleme denke ich liegen nicht vor, weil der Plan keine NATURAL aufweist. Außerdem habe ich probeweise mal Indizes auf die verwendeten Felder gelegt, ohne das es den Summer SQL positiv beeinflußte.

Umgangssprachlich brauche ich alle Lagerkarte aus SQL a, deren PK (=Feld ref) auch in der Ergebnisliste von sql.b steht.

Als Subselect sieht das so aus (der IN Operator vermiest mir hier wahrscheinlich das Geschäft, wird der eventuell bei jeder Ergebniszeile durchgeführt?)
ausblenden SQL-Anweisung
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
SELECT * FROM LAGERKARTE
WHERE (LAGERORT BETWEEN '00-000-00'  AND '99-999-99') AND ((BESTAND<=0) or
(BESTAND<LAGERKARTE.MINDESTMENGE)) and (KEINLAGERTEIL=0)
and ref in
(SELECT ref0 FROM artikelhistorie
WHERE artikelhistorie.zeitstempel between '1.1.2007' and '1.9.2007'
and artikelhistorie.buchungstyp in (4,5,7,8,9,12,14,16)
and artikelhistorie.mengenaenderung is not Null
and artikelhistorie.mengenachaenderung<=0
group by artikelhistorie.ref0
ORDER BY LAGERORT ASC


Als Ergebnismenge erwarte ich ungefähr 60 bis 80 Rows.
Hat da noch jemand einen Tip, um dem SQL bzw. dem Optimzer/Planer auf die Sprünge zu helfen?
motion Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 295

XP, Linux
D7 Prof
BeitragVerfasst: Fr 10.08.07 13:20 
Ich glaube ich hab's doch gerade gefunden:
ausblenden SQL-Anweisung
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
SELECT * FROM LAGERKARTE
join
(SELECT ref0 FROM artikelhistorie
WHERE artikelhistorie.zeitstempel between '1.1.2007' and '1.9.2007'
and artikelhistorie.buchungstyp in (4,5,7,8,9,12,14,16)
and artikelhistorie.mengenaenderung is not Null
and artikelhistorie.mengenachaenderung<=0
group by artikelhistorie.ref0) as B
on lagerkarte.ref=b.ref0
WHERE (LAGERORT BETWEEN '00-000-00'  AND '99-999-99') AND ((BESTAND<=0) or
(BESTAND<LAGERKARTE.MINDESTMENGE)) and (KEINLAGERTEIL=0)
ORDER BY LAGERORT ASC


Bisher habe ich immer einen
join artikelhistorie on Lagerkarte.ref=artikelkarte.ref0 gemacht, und dann mit where alles weiter eingeschränkt,was wohl ungeschickt ist.
Ich habe jetzt den Join direkt auf den SQL B angesetzt und das Ergebnis sieht gut aus (80Rows, <2s Bearbeitungszeit).