2009-06-14 20 views
2

Ich habe 2 Tabellen (?):Komplexe SQL-Abfrage beitreten

1) Tabelle Masterdates, die alle Daten seit Jan enthält 1, 1900

2) Tabelle Stockdata die Bestandsdaten in Form Datum enthält, Symbol, offen, hoch, tief, in der Nähe, Volumen (Primärschlüssel = Datum, Symbol)

Das ist, was ich suche

mdate, sdate, Symbol, (dargestellt hier im CSV-Format) Öffnen abrufen , Hoch, ...

6/4/2001,6/4/2001, Foo, 47,49, ...

6/5/2001, null, null, null, null, ...

6/6/2001.6/6/2001, Foo, 54,56, ...

wobei MDate von Masterdates und SDate von Stockdata stammt. Ich muss die Ausgabe mit dem ersten (frühesten) Extent-Datum für das gewünschte Symbol (in diesem Beispiel Foo, beginnend am 6.4.2001) in Stockdata beginnen und dann alle Daten in Masterdates bis einschließlich des letzten einschließen (spätestes) verfügbares Datum für das gewünschte Symbol in Stockdata, Ausgabe von Nullen, wenn es keinen entsprechenden Stockdata-Datensatz für einen gegebenen Masterdate-Datensatz in dem beschriebenen Bereich gibt.

Gibt es eine Möglichkeit, dies in einer einzigen Abfrage, einer Reihe von Abfragen und/oder durch Hinzufügen von Hilfstabellen zu tun, die zu schnellen Ergebnissen führen? Oder muss ich Obermengen von dem, was ich will, ausgeben und dann die endgültige Ausgabe mit meiner (nicht-SQL-) Programmiersprache erstellen?

TIA

+0

Welches SQL-System genau? MS SQL Server? MySQL? –

Antwort

7

Geprüft Sqlite3, Ihre DB Implementierung

SELECT m.date, 
     s.symbol, 
     s.open, 
     s.high, 
     s.low, 
     s.close, 
     s.volume 
FROM  masterdate AS m LEFT OUTER JOIN 
     stockdata AS s ON m.date = s.date 
AND  s.symbol = 'Foo' 
WHERE m.date >= (SELECT MIN(date) FROM stockdata WHERE symbol = 'Foo') 
AND  m.date <= (SELECT MAX(date) FROM stockdata WHERE symbol = 'Foo') 

unterscheiden Wenn dies nicht ausgeführt Quicky genug ist, dann kann man pronably Leistung verbessern, indem Variablen für Minimal- und Maximalwert in einer Abfrage Einstellung und dann mit denen in der Hauptabfrage. Dies würde Ihnen mindestens einen Indextreffer ersparen.

So (In SQL Server Syntax)

SET @symbol = 'Foo' 

SELECT @mindate = MIN(date), 
     @maxdate = MAX(date) 
FROM stockdata 
WHERE stockdata.symbol = @symbol 


SELECT m.date, 
     s.symbol, 
     s.open, 
     s.high, 
     s.low, 
     s.close, 
     s.volume 
FROM  masterdate AS m LEFT OUTER JOIN 
     stockdata AS s ON m.date = s.date 
AND  s.symbol = @symbol 
WHERE m.date BETWEEN @mindate AND @maxdate 

Sie müssen auch sicher sein, dass Sie einen Index für masterdate.date und einen zusammengesetzten Index auf stockdata (Datum, Symbol) haben.

+0

22 Sekunden auf einer 6 GB db. Schneller als ich dachte, aber nicht dort, wo ich es brauche. Ich denke, wenn ich die Daten austeile, kann ich das auf etwas viel Besseres reduzieren (derzeit habe ich täglich, Intraday, Aktien, Futures, Index, Sie nennen es, Daten in einer einzigen Tabelle). Vielen Dank! – user119282

1

Wenn Sie SQLServer verwenden, können Sie eine gespeicherte TSQL-Prozedur verwenden, um die Ergebnisse zurückzuerhalten. Es wird im Wesentlichen zwei Linien haben:

1), um das erste Datum für Daten verfügbar 2) Eine Abfrage mit einer äußeren Verknüpfung zu erhalten

Wenn Sie Oracle verwenden, können Sie eine PL/SQL verwenden ein ähnliches zu schreiben (obwohl ein bisschen komplizierter) gespeicherte Prozedur, um die gewünschte Antwort zu berechnen.

3

Dies ist ein klassisches LEFT JOIN:

SELECT * FROM masterdates 
    LEFT JOIN stockdata ON masterdates.date = stockdata.date;

Das sollte natürlich zu verfeinert werden nur die gewünschten Spalten zurück.

+0

Aber das wird mir alles in den Masterdates geben, oder? – user119282

0

Ich würde vorschlagen, die fehlenden Einträge aus der Tabelle Stockdata auszufüllen und einen inneren Join zu verwenden.Sollte viel schneller sein.

+0

Können Sie es bitte ein bisschen mehr erklären? – user35443