MySQLのクエリのパズル - 最新の日付であったであろうものを見つけます

StackOverflow https://stackoverflow.com/questions/2837441

質問

私はすべての上に見てきたと私は1つが可能であることを確認感じるものの、まだ、これを処理するインテリジェントな方法を発見していない。

履歴データの一つの表では、四半期ごとの情報を有している:

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));
(非常に大きい)、履歴データの

別のテーブルは、毎日の情報が含まれています:

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));

qtr_IDフィールドは、データベースに取り込まことを日々のデータのフィードの一部ではありません - その代わり、私が最も最近のあったであろうものを使用して、遡及Quarterly.unique_ID行IDと毎日のテーブルにqtr_IDフィールドを移入する必要がありますそのデータソースに対してそのDaily.date_posted上の四半期データます。

例えば、四半期のデータがある場合

  

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

、毎日のデータがある。

  

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

そして、私たちが望むだろう? qtr_IDその日のそのデータソースの直近の四半期として「102」を割り当てるフィールド、および&&も「102」になり、かつ^^ 104 'になります。

の課題は、両方のテーブル(特に毎日のテーブル)は実際には非常に大きいことを含む、それらが繰り返し日付を取り除くために正規化または他の方法で最適化され、そして特定の毎日のエントリを全く前の四半期のエントリが存在しないことはできません。

通常、私の構文はどこかを壊している - 私はDATEDIFF(チャレンジがゼロよりDateDiff関数大きいの最小値を見つけることです)、および他の試みが、何も私のために働いていないを使用して、参加する各種のを試してみました。すべてのアイデアは歓迎 - 私は任意の基本的な考え方や概念およびレポートバックを実行します。

役に立ちましたか?

解決

のようなものを使用して四半期のIDのためだけのサブクエリます:

(
 SELECT unique_ID 
 FROM Quarterly 
 WHERE 
     datasource = ? 
     AND date_posted >= ? 
 ORDER BY
     unique_ID ASC
 LIMIT 1
)
(そうでない場合はorder by date_postedもちろん、これはおそらく、あなたに最高のパフォーマンスを与えることはありません、それは日付が順次四半期に追加されていることを前提としています。しかし、それはあなたの問題を解決する必要があります。

あなたはINSERTテーブルのためのあなたのUPDATEフィールドの値としてごqtr_IDまたはDaily文にこのサブクエリを使用することになります。

他のヒント

以下の意図どおりに動作しているように見えますが、それは確かに醜いです(同じDATEDIFFへの3回の呼び出しで!!)、おそらく誰かがそれをさらに減らすか、それを改善することができるかもしれない作業クエリを見てます:

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));

このクエリの詳細仕事の後、私はオリジナルのコンセプトを超える巨大なパフォーマンスの改善になってしまいました。 HASHを用いて毎日私にBTREEを使用した(データソース、date_posted)及び(date_posted、データソース)にインデックスを作成し、(データソース)の上に、そして四半期Iで同じことをやった - 最も重要な改善は、毎日および四半期テーブルの両方にインデックスを作成することでした事。これはやりすぎですが、それは、私は、クエリエンジンが使用できるというオプションを持っていたことを確認しました。それはそれはあったものの1%未満にクエリ時間を削減しました。 (!!)

そこで、私は、私はMAX(への呼び出しを使用するので、私の特定の状況与えられた私は、適切なUNIQUE_IDを取得するために)の代わりにORDER BYとLIMITのMAX()を使用することができることを学びました。それは約20%でクエリ時間を低減します。

最後に、私はInnoDBストレージエンジンを搭載した私は、セグメント、私は少し肘グリースとスクリプトとマルチスレッドクエリに私を許さいずれかのクエリと更新されたことを毎日のテーブルのチャンクをできたことを知りました。並列処理がうまく働いていた、すべてのスレッドが直線的にクエリ時間を削減します。

だから、より良い自分の最初の試みよりも、文字通り1000倍を実行している基本的なクエリがあります:

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
;
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top