パラメータ値が、表示されているように常に適切な形式である場合、4 桁の年、ダッシュ、および 2 桁の月が空白のない垂直バーで区切られている場合、次のようにデータベースに検索を実行させることができます。
INSTR(CONCAT('|',parameter_value,'|'),DATE_FORMAT(e.sDate,'|%Y-%m|')) > 0
または、空白と区切り文字をもう少し自由に使用するには、
INSTR(parameter_value,DATE_FORMAT(e.sDate,'%Y-%m')) > 0
日付列で MONTH 関数と YEAR 関数を実行し、リテラルとの等価比較を行うよりも、パフォーマンスが低下するとは思いません。これらの述語はどちらもサージ可能ではありません (つまり、インデックスの使用を許可します)。
このアプローチには、SQL ステートメントを動的に作成して可変数の引数を渡す必要がないため、ストアド プロシージャで行う作業が少なくなるという利点があります。(テストするコードが少なくなります。)
パラメーターをオプションにする必要がある場合、つまり、パラメーターが指定されていない場合 (デフォルトで空の文字列) は、まったく同じステートメントで日付列に述語を適用することを避けることができます。 SQL テキスト:
(paramater_value = '' OR INSTR(parameter_value,DATE_FORMAT(e.sDate,'%Y-%m')) > 0)
述語を検索可能にするには、SQL でネイティブの日付列を参照するようにします。これを範囲スキャンとして記述すると、SQL テキストは次の形式になります。
( ( e.sDate >= CONCAT('2012-07','-01') AND
e.sDate < DATE_ADD(CONCAT('2012-07','-01'),INTERVAL 1 MONTH) )
OR ( e.sDate >= CONCAT('2012-10','-01') AND
e.sDate < DATE_ADD(CONCAT('2010-10','-01'),INTERVAL 1 MONTH) )
OR ( e.sDate >= CONCAT('2013-02','-01') AND
e.sDate < DATE_ADD(CONCAT('2013-02','-01'),INTERVAL 1 MONTH) )
インデックスを使用できるということだけが、パラメーター文字列を解析し、可変数の述語を使用してクエリ テキストを作成し、動的 SQL を使用し、すべてをテストするという面倒な作業を行う唯一の正当な理由です。 . 一時テーブルを作成し、パラメーター文字列から解析された "yyyy-mm" 値をロードして、それを結合述語で参照したいと思います。
CREATE TEMPORARY TABLE my_temp_parameter
( yyyy SMALLINT NOT NULL COMMENT 'year yyyy'
, mm TINYINT UNSIGNED NOT NULL COMMENT 'month, 1-12'
, PRIMARY KEY (yyyy,mm)
)
(結合によって「余分な」行が生成されないようにするため、これらの 2 つの列には一意の制約が必要です。)クエリでは、一時テーブルを次のように参照します。
FROM ... e
JOIN my_temp_parameter p
ON e.sDate >= CONCAT(p.yyyy,'-',p.mm,'-01') AND
e.sDate < DATE_ADD(CONCAT(p.yyyy,'-',p.mm,'-01'),INTERVAL 1 MONTH)
このアプローチの利点は、動的 SQL をデバッグする必要がなく、SQL テキストを生成するコードを保守する必要がないことです。より簡単にテストできる静的 SQL テキストを使用したいと考えています。
それがあなたの質問に答えていない場合は申し訳ありません。しかし、ストアド プロシージャ内に動的 SQL を作成する道に進む前に (それが必要な場合もあります)、他のアプローチを試して、別の適切な解決策が見つからない場合は動的 SQL に戻ります。 .