Autor |
Beitrag |
fahrstuhl65
      
Beiträge: 30
|
Verfasst: Mi 12.10.11 16:12
Hallo,
ich habe eine MSSQL DB die ein etwa so ausschaut:
DateTime LastTrade Volume
2011-03-17 09:06:09.000 6598.5 2
2011-03-17 09:06:09.000 6599 1
2011-03-17 09:06:10.000 6599 1
2011-03-17 09:06:11.000 6599 5
2011-03-17 09:06:11.000 6599 1
2011-03-17 09:06:11.000 6598.5 1
2011-03-17 09:06:12.000 6599 1
Für jede Minute gibt es einige, manchmal ein paar hundert Zeilen in denen ein Kurs steht (LastTrade).
Nun möchte ich herausfinden was das jeweilige Hoch und Tief einer Minute ist
und das Ergebnis in eine neue Tabelle wie folgt schreiben:
DateTime Hoch Tief
2011-03-17 09:06:00.000 6598.5 6580
2011-03-17 09:07:00.000 6593 6590
2011-03-17 09:08:00.000 6593 6590
Ich hab nur leider keine Ahnung wie ich das bewerkstelligen soll - kann mir da jemand helfen ?
ich such keine fertige Lösung, nur einen Weg den ich dann versuchen kann zu gehen
Die Datenbank über die ich das machen muss hat ca. 10 Millionen Datensätze.
Freue mich auf Hilfe
gruß
fahrstuhl
|
|
Horschdware
      
Beiträge: 744
Erhaltene Danke: 54
Win XP Pro, Win 7 Pro x64
Delphi 7, Delphi XE, C++ Builder 5, SAP R/3
|
Verfasst: Mi 12.10.11 16:21
Ich gehe mal davon aus, du suchst nur nach den passenden SQL-Befehlen, ja?
Dann bekommst du die Maxima und Minima wie folgt:
Quelltext 1: 2: 3:
| SELECT max(LastTrade) AS maximum, min(LastTrade) AS minimum FROM btlWieAuchImmer WHERE DateTime = GewünschterZeitpunkt |
Dann für jeden Zeitpunkt einen neuen Eintrag in der zweiten Tabelle anlegen.
_________________ Delphi: XE - OS: Windows 7 Professional x64
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mi 12.10.11 16:30
Hallo,
das Problem ist die Spalte 'DateTime', da dort ja unterschiedliche Sekunden eingetragen sind, aber nur nach Minuten gruppiert werden soll.
Evtl. helfen dazu die Date and Time Functions (Transact-SQL).
Edit: unter ask.metafilter.com/4...QL-results-by-minute scheint es gute Ansätze dafür zu geben (DATEPART, CONVERT, DATEDIFF)...
Zuletzt bearbeitet von Th69 am Mi 12.10.11 16:39, insgesamt 1-mal bearbeitet
|
|
fahrstuhl65 
      
Beiträge: 30
|
Verfasst: Mi 12.10.11 16:34
@ Horschdware
ja danke - das wäre ein gangbarer Weg denke ich !
Ich werde mich mal dran wagen und hab dann sicher noch ein paar Fragen
@ TH69
das ist in der Tat richtig, gibt es denn für den oben genannten SQL Query auch die Möglichkeit
Between 16032011 08:00.00.000 AND 16032011 08.00.59.999 zu suchen ?
|
|
fahrstuhl65 
      
Beiträge: 30
|
Verfasst: Do 13.10.11 12:03
Also das mit dem Between suchen funktioniert nun mit diesem Query:
SQL-Anweisung 1: 2: 3:
| SELECT MAX(LastTrade) AS maximum FROM datei1 WHERE (DateTime BETWEEN @p1 AND @p2) |
Für @p1 und @p2 übergebe ich dann die Zeiträume.
Gebe ich das das per Hand ein, funktioniert die Abfrage, aber im Code habe ich folgendes stehen:
C#-Quelltext 1: 2: 3: 4: 5:
| string maximum;
DateTime beginn = new DateTime(2011, 03, 17, 09, 06, 00, 000); DateTime ende = new DateTime(2011, 03, 17, 09, 06, 59, 999); maximum = GesamtdatenTableAdapter_button1_click.maximumabfrage(beginn, ende); |
Versuche ich zu kompilieren, zeigt er mir:
Fehler 1 Der Typ "object" kann nicht implizit in "string" konvertiert werden. Es ist bereits eine explizite Konvertierung vorhanden. (Möglicherweise fehlt eine Umwandlung.)
Das man da was casten muss, ist mir eigentlich klar, aber ich weiss beim besten willen nicht wie,
in string casten geht nicht und hier hake ich echt grade, ich denke das ist total banal, aber ich
komm da grade nicht weiter.
Kann mir einer weiterhelfen ?
Zuletzt bearbeitet von fahrstuhl65 am Do 13.10.11 13:03, insgesamt 1-mal bearbeitet
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Do 13.10.11 12:28
Die MAX Aggregatfunktion liefert sicher keinen string sondern einen Zahlenwert entsprechend dem Typ von LastTrade. Wie sieht den die MethodenSignatur von maximumabfrage aus und welchen Typ hat LastTrade?
Allgemein würde ich von casten in diesem Kontext abraten sondern du solltest einen expliziten Aufruf von Convert.ToMeinKonkreterZielTyp vornehmen (wenn den überhaupt nötig).
PS. Stilfragen. Du hast einen TableAdapter mit '_button1_click' im Namen? Du schreibst Methoden klein?
|
|
fahrstuhl65 
      
Beiträge: 30
|
Verfasst: Do 13.10.11 12:34
also die Column LastTrade in der DB hat Varchar als Datentyp - also sollte das doch passen ?
Ich hab ja sowas hier auch schon versucht:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7:
| string maximum; DateTime beginn = new DateTime(2011, 03, 17, 09, 06, 00, 000); DateTime ende = new DateTime(2011, 03, 17, 09, 06, 59, 999); maximum = GesamtdatenTableAdapter_button1_click.maximumabfrage(Convert.ToString(beginn), Convert.ToString(ende)); |
Mit dem Ergebnis:
Argument: Kann nicht von "string" in "System.DateTime?" konvertiert werden.
zu den Stilfragen, ja das mit dem TableAdaptern habe ich nur gemacht um zu wissen aus welcher Funktion der TableAdapter
aufgerufen wurde, falls mal ne Exception geworfen wird, ist sicher kein guter Stil, hat mir aber schon mehrfach geholfen.
Das mit den Methoden, ich bin halt noch Anfänger 
Zuletzt bearbeitet von fahrstuhl65 am Do 13.10.11 13:03, insgesamt 1-mal bearbeitet
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Do 13.10.11 12:46
Zitat: | also die Column LastTrade in der DB hat Varchar als Datentyp - also sollte das doch passen ? |
Nun ja wenn dir bewußt ist was das Maximum einen strings bedeutet ist das ok (z.B.ist '2' maximaler als '10' und bei einem Datum in einem string hast du die gleiche Problematik)
Zitat: | maximum = GesamtdatenTableAdapter_button1_click.maximumabfrage(Convert.ToString(beginn), Convert.ToString(ende)); |
Ich dachte eher der AusgabeTyp wäre das Problem nicht die Eingabeparameter. Zeig lieber mal die Methodensignatur von maximumabfrage.
Und nur nochmal zur Zusammenfassung LastTrade ist ein varchar und dein Feld DateTime ist tatsächlich auch vom Typ DateTime oder ist das auch ein varchar und heißt nur Datetime? Dann Viel Spass 
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Do 13.10.11 12:53
Hallo fahrstuhl65,
bitte formatiere deine Beiträge mit den entsprechenden Tags (SQL, C#, etc.). Dazu kannst du deine Beiträge editieren und mit der ComboBox aus "Bereiche" den entsprechenden Tag auswählen und dann den "+"-Button drücken.
Danke.
|
|
fahrstuhl65 
      
Beiträge: 30
|
Verfasst: Do 13.10.11 13:00
Du hast natürlich Recht - eigentlich müsste die Column auch auf float oder ähnliches
gesetzt sein, in den Tests hats aber funktioniert bisher, ändere ich aber noch mal !
War mir so noch nicht bewusst
Das Feld DateTime ist tasächlich vom Typ DateTime in der DB - das habe ich beim Import
schon so hinbekommen.
Aber was meinst du mit der "Methodensignatur" - wo finde ich die ?
Stehe im Moment auf dem Schlauch....
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Do 13.10.11 13:31
Ich will wissen wie die maximumabfrage Methode aussieht.
Also irgendwie sowas
C#-Quelltext 1:
| public string maximumabfrage(DateTime p1, DateTime p2) |
|
|
fahrstuhl65 
      
Beiträge: 30
|
Verfasst: Do 13.10.11 13:54
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36:
| public virtual object maximumabfrage(global::System.Nullable<global::System.DateTime> p1, global::System.Nullable<global::System.DateTime> p2) { global::System.Data.SqlClient.SqlCommand command = this.CommandCollection[1]; if ((p1.HasValue == true)) { command.Parameters[0].Value = ((System.DateTime)(p1.Value)); } else { command.Parameters[0].Value = global::System.DBNull.Value; } if ((p2.HasValue == true)) { command.Parameters[1].Value = ((System.DateTime)(p2.Value)); } else { command.Parameters[1].Value = global::System.DBNull.Value; } global::System.Data.ConnectionState previousConnectionState = command.Connection.State; if (((command.Connection.State & global::System.Data.ConnectionState.Open) != global::System.Data.ConnectionState.Open)) { command.Connection.Open(); } object returnValue; try { returnValue = command.ExecuteScalar(); } finally { if ((previousConnectionState == global::System.Data.ConnectionState.Closed)) { command.Connection.Close(); } } if (((returnValue == null) || (returnValue.GetType() == typeof(global::System.DBNull)))) { return null; } else { return ((object)(returnValue)); } } |
Das steht im Designer - ist ja eine automatisch generierte Abfrage, meinst du das ?
|
|
fahrstuhl65 
      
Beiträge: 30
|
Verfasst: Do 13.10.11 14:06
Ach ich habs,....sorry.....
so ists richtig:
C#-Quelltext 1: 2: 3: 4: 5: 6:
| string maximum; DateTime beginn = new DateTime(2011, 03, 17, 09, 06, 00, 000); DateTime ende = new DateTime(2011, 03, 17, 09, 06, 59, 999); maximum = Convert.ToString(GesamtdatenTableAdapter_button1_click.maximumabfrage(beginn, ende)); |
Das was zurückgegeben wird muss in den String umgewandlet werden
So, nun bin ich wieder einen Schritt weiter, nun muss ich mal versuchen wie ich es hinbekomme eine Schleife zu basteln,
die a) immer den Wert der beginn und ende zugewiesen wird um 1 erhöht und b) das ergebnis in eine neue
Datenbank schreibt um dann irgendwann da hinzukommen wo ich hin will
Aber - einen Schritt bin ich dann doch schon mal weiter ! Wenn jemand eine Idee für die Schleife hat,
freu ich mich natürlich !
|
|
fahrstuhl65 
      
Beiträge: 30
|
Verfasst: Do 13.10.11 14:13
btw - ich hab jetzt auch die Spalte Lasttrade vom Typ her auf "float" gewechselt 
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Do 13.10.11 16:13
Wenn ich dich richtig verstanden habe und du den Max/Min Wert je Minute willst brauchst du nicht mehrere Abfragen.
Ist in dem Fall sogar recht einfach da der SmallDateTime Datentyp zufällig (mehr oder weniger) genau ein Präzision von einer Minute hat. Einmal kurz hin und zurück casten und alle Daten sind auf die Minute normiert.
SQL-Anweisung 1: 2: 3: 4:
| select Max(LastTrade), Min(LastTrade), CAST(CAST([DateTime] as SmallDateTime) as DateTime) from datei1 where [DateTime] between @p1 AND @p2 group by CAST(CAST([DateTime] as SmallDateTime) as DateTime) |
So bekommst du aber nur natürlich nur ein Ergebnis für Minuten in denen es auch Daten gibt. Beim selber 'hochzählen' der Minuten bekommst du natürlich auch leere Ergebnisse.
Zuletzt bearbeitet von Ralf Jansen am Do 13.10.11 16:55, insgesamt 2-mal bearbeitet
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Do 13.10.11 16:44
Hall Ralf,
toller Trick - muß ich mir merken.
Du meinst aber sicher 'DateTime' anstatt 'LastTrade' in dem CAST in der oberen Zeile?
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Do 13.10.11 16:51
Zitat: | Du meinst aber sicher 'DateTime' anstatt 'LastTrade' in dem CAST in der oberen Zeile? |
Nein. LastTrade scheint ein Kurswert zu sein kein Datum. Ich hatte es so verstanden das er seine DateTime Spalte tatsächlich DateTime genannt hat. Und wenn dem so ist sollte er spätestens jetzt gemerkt haben wie missverständlich das ist, Danke
Edit: Jetzt sehe ich es auch. Im anderen Cast sollte es ebenfalls [DateTime] heißen nicht LastTrade. Wird korrigiert.
|
|
fahrstuhl65 
      
Beiträge: 30
|
Verfasst: Do 13.10.11 16:59
naja mit dem LastTrade habt ihr schon Recht, könnte man missverstehen,
ich hab das aber so übernommen aus einem CSV
Es ist der letzte Kurs der festgestellt wurde zu dem jeweiligen Zeitpunkt.
Das mit dem Casten muss ich mir erstmal anschauen in Ruhe -
das habe ich so aus dem Stand noch nicht verstanden, muss nur leider jetzt weg,
melde mich morgen früh - danke erstmal !!!
|
|
fahrstuhl65 
      
Beiträge: 30
|
Verfasst: Fr 14.10.11 10:33
Ralf Jansen hat folgendes geschrieben : | Wenn ich dich richtig verstanden habe und du den Max/Min Wert je Minute willst brauchst du nicht mehrere Abfragen.
|
WOW - du hast Recht, ich muss jetzt noch verifizieren ob das richtig ist was da rauskommt, es sieht aber sehr danach aus !
Vor allem - und das ist natürlich noch wesentlich besser als das was ich vorhatte, muss ich mich so nicht um die leeren Zeilen
am Ende wieder kümmern,....sondern er macht das nur für die Zeiten, die da sind scheinbar.
Und wenn ich WHERE... p1 und p2 wegnehme macht er das ja sofort über alle scheinbar.
Wahnsinn, ich werd jetzt mal verifizieren ob die Ergebnisse auch "stimmen",....melde mcih dann wieder!
|
|
fahrstuhl65 
      
Beiträge: 30
|
Verfasst: Fr 14.10.11 11:19
zu früh gefreut  Also das was er macht stimmt nur bedingt, es gibt immer eine Verschiebung
von 1 bis 1,5 Punkten,....warum hab ich noch nicht verstanden es gibt kein Muster.
Ziel ist es ja das Maximum und das Minimum JEDER Minute zu finden, wenn ich also folgende
Abfrage starte:
SQL-Anweisung 1: 2: 3: 4: 5:
| SELECT [DateTime] ,[LastTrade] ,[Volume] FROM [Fdax_bereinigt].[dbo].[datei1] WHERE DateTime BETWEEN '16/03/2011 09:05:00.000' AND '16/03/2011 09:05:59.999' order by LastTrade |
dann erhalte ich als kleinsten Wert 6711 und als höchsten Wert 6715,5.
In dieser Abfrage hier:
SQL-Anweisung 1: 2: 3:
| select Max(LastTrade) AS Maximum, Min(LastTrade) AS Minimum, (CAST(CAST([DateTime] as SmallDateTime) as DateTime)) AS Datum from datei1 group by CAST(CAST([DateTime] as SmallDateTime) as DateTime)order by Datum |
die ich nur um die Bezeichner verändert habe sagt er mit für die Minute 09:05:00 dann 6711 und 6714
Warum das so ist, versteh ich jetzt noch nicht ganz, das liegt aber daran das ich nicht ganz verstehe was die untere Abfrage eigentlich macht
Wenn die untere Abfrage das exakt könnte, wäre das natürlich der Hit, müsste ich nichts programmieren und könnte dann zum letzten Schritt
über gehen, aber da stimmt ja noch etwas nicht, hat noch einer eine Idee ?
|
|
|