Frage

Ich habe alle übersehen und noch nicht gefunden eine intelligente Art und Weise zu handhaben, aber ich bin sicher, man ist möglich:

Eine Tabelle mit historischen Daten hat vierteljährlich Informationen:

CREATE TABLE Quarterly (
unique_ID INT UNSIGNED NOT NULL,
date_posted DATE NOT NULL,
datasource TINYINT UNSIGNED NOT NULL,
data FLOAT NOT NULL,
PRIMARY KEY (unique_ID));

Eine weitere Tabelle von historischen Daten (die sehr groß ist) enthält täglich Informationen:

CREATE TABLE Daily (
unique_ID INT UNSIGNED NOT NULL,
date_posted DATE NOT NULL,
datasource TINYINT UNSIGNED NOT NULL,
data FLOAT NOT NULL,
qtr_ID INT UNSIGNED,
PRIMARY KEY (unique_ID));

Das qtr_ID Feld ist nicht Teil der Zufuhr von täglich Daten, dass die Datenbank gefüllt - stattdessen ich brauche das qtr_ID Feld in der Tagestabelle rückwirkend zum Auffüllen mit der Quarterly.unique_ID Zeilen-ID, mit, was den jüngst gewesen wäre Quartalsdaten auf, dass Daily.date_posted für diese Datenquelle.

Zum Beispiel, wenn die Quartalsdaten sind

  

101 2009-03-31 1 4.5
   102 2009-06-30 1 4.4
   103 2009-03-31 2 7.6
   104 2009-06-30 2 7.7
   105 2009-09-30 1 4.7

und die täglichen Daten

  

1001 2009-07-14 1 3.5 ??
  1002 2009-07-15 1 3.4 &&
  1003 2009-07-14 2 2.3 ^^

dann würden wir das ?? qtr_ID Feld zu diesem Zeitpunkt als das jüngste Quartal für diese Datenquelle zugewiesen ‚102‘ werden, und && wäre auch ‚102‘, und ^^ wäre ‚104‘.

Die Herausforderungen sind, dass beide Tabellen (vor allem die tägliche Tabelle) sind eigentlich sehr groß ist, kann sie nicht loswerden der repetitiven Daten normalisiert werden oder auf andere Weise optimiert und für bestimmte tägliche Einträge gibt es keinen vorhergehenden Quartals Eintrag.

Ich habe eine Vielzahl von Verknüpfungen versucht, mit datediff (wobei die Herausforderung darin, den Mindestwert von DATEDIFF größer findet als Null), und andere Versuche, aber nichts für mich arbeiten - in der Regel meiner Syntax irgendwo bricht. Irgendwelche Ideen willkommen - Ich werde keine grundlegenden Ideen oder Konzepte und Bericht zurück ausführen

.
War es hilfreich?

Lösung

Just Unterabfrage für die Quartal-ID mit so etwas wie:

(
 SELECT unique_ID 
 FROM Quarterly 
 WHERE 
     datasource = ? 
     AND date_posted >= ? 
 ORDER BY
     unique_ID ASC
 LIMIT 1
)

Natürlich ist dies wahrscheinlich nicht geben Ihnen die beste Leistung, und es wird davon ausgegangen, dass Daten Quarterly hinzugefügt werden sequentiell (sonst order by date_posted). Es sollte jedoch Ihr Problem lösen.

Sie würden diese Unterabfrage auf Ihren INSERT oder UPDATE Aussagen als den Wert Ihres qtr_ID Feldes verwenden für Ihre Daily Tabelle.

Andere Tipps

Die folgenden scheint zu funktionieren genau wie beabsichtigt, aber es ist sicherlich hässlich (mit drei Anrufe zum gleichen DATEDIFF !!), vielleicht durch eine funktionierende Abfrage jemand sehen könnte in der Lage sein, um sie weiter zu reduzieren könnten oder verbessern:

UPDATE Daily SET qtr_ID = (select unique_ID from Quarterly
WHERE Quarterly.datasource = Daily.datasource AND
DATEDIFF(Daily.date_posted, Quarterly.date_posted) = 
(SELECT MIN(DATEDIFF(Daily.date_posted, Quarterly.date_posted)) from Quarterly
WHERE Quarterly.datasource = Daily.datasource AND
DATEDIFF(Daily.date_posted, Quarterly.date_posted) > 0));

Nach mehr Arbeit an dieser Abfrage, landete ich mit enormen Leistungsverbesserungen gegenüber dem ursprünglichen Konzept auf. Die wichtigste Verbesserung war Indizes sowohl in den Tages- und Quartal Tabellen erstellen - in Daily I Indizes erstellt auf (Datenquelle, date_posted) und (date_posted, Datenquelle) weiter verwendet BTREE und auf (Datenquelle) HASH weiter verwenden, und in Quarterly Ich tat die gleichen Sache. Das ist übertrieben, aber es stellte sicher, dass ich eine Option hatte, dass die Abfrage-Engine nutzen könnten. Dass reduzierte die Abfragezeit auf weniger als 1% von dem, was es gewesen war. (!!)

Dann erfuhr ich, dass meine besonderen Umstände gegeben, ich könnte MAX () verwende, statt ORDER BY und LIMIT so dass ich einen Aufruf an MAX () verwende Sie die entsprechende unique_id zu bekommen. Dass die Abfragezeit um etwa 20% reduziert werden.

Schließlich erfuhr ich, dass mit der Speicher-Engine InnoDB Segment konnte ich das Stück des Tag Tisches, dass ich mit einer Abfrage wurde die Aktualisierung, die mich erlaubte Multi-Thread die Anfragen mit einem wenig Ellenbogen-Fett und Scripting. Die parallele Verarbeitung funktionierte gut und jeder Thread reduziert die Abfrage Zeit linear.

Also, die grundlegende Frage, die buchstäblich 1000 mal besser als mein eigener erster Versuch ausgeführt wird:

UPDATE Daily
SET qtr_ID =
(
  SELECT MAX(unique_ID)
  FROM Quarterly
  WHERE Daily.datasource = Quarterly.datasource AND
        Daily.date_posted > Quarterly.dateposted
)
WHERE unique_ID > ScriptVarLowerBound AND
      unique_ID <= ScriptVarHigherBound
;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top