2011-06-24 7 views
0

私は周りを見回していて、自分のニーズを満たす解決策を見つけることが難しいと思われるので、お手伝いができることを願っています。 (私はMySQLの方がやや新しくなっていますが、SQL ServerとOracleの豊富な経験がありますが)。複数のテーブルからデータを収集するためのMySQLループ

私はいくつかのテーブルを持つデータベースを持っています。

最初のテーブルは、基本的な情報を格納し、cp_def呼ばれる定義テーブルである:cp_defテーブルの各レコードに対して、

cid (pkey) status 
------------------- 
10001  0 
10002  1 

そして、対応cp_ある[CID]表(ここで、[CID ]はcp_defテーブルのcid値です)。例:

私はすべてのcp_ [CID]テーブル、出力のすべてのレコードのためのコードとdate_expired列の値に(シェルスクリプトとcronジョブの一部として)毎日、動的クエリを実行する必要が
table: cp_10001 

id(pkey) code  date_issued date_expired 
------------------------------------------------- 
1   ABC123 2011-06-23  2011-06-30 
2   CYG124 2011-06-23  2011-06-30 


table: cp_10002 

id(pkey) code  date_issued date_expired 
------------------------------------------------- 
1   CAC126 2011-06-23  2011-06-30 
2   VGC254 2011-06-23  2011-06-30 

date_issued値は前日の日付です。

質問があります(下記参照)。ただし、新しいcp_ [CID]テーブルを追加するたびに、別のUNION ALLステートメントを手動で追加してクエリを終了する必要があります。

SELECT code, date_expired 
FROM mydatabase.cp_10001 
WHERE DATE(date_issued) = DATE_SUB(CURDATE(), INTERVAL 1 DAY); 
UNION ALL 
SELECT code, date_expired 
FROM mydatabase.cp_10002 
WHERE DATE(date_issued) = DATE_SUB(CURDATE(), INTERVAL 1 DAY); 

私の究極の目標は、毎回新しいcp_ [CID]テーブルがデータベースに追加されるように、それは手動の介入を必要としない、それが実行されます時に、programmaticly上記のクエリを生成することです。

私はビューを使ってみました。しかし、テーブルを追加すると、新しいテーブルを考慮して、ビューを手動で変更する必要があるように見えました。

各cp_ [CID]テーブルがcp_defテーブル(INFORMATION_SCHEMAテーブル)にリストされているとすれば、私は動的クエリを構築するために何らかのループを実行できると考えていましたが、理解した。これを短く保つために、cp_defテーブルをループして失敗した試みを投稿して動的クエリを作成しないようにします。

このようなクエリを作成するための正しい方向に私を指差してくれれば、助けてくれれば幸いです。もし私が何か見落としてしまったら、私は謝ります。私は、私が探しているものを、さまざまなフレーズで正確に検索しようとしましたが、無駄です。

答えて

0

私は(代わりに、多くのCPの_ ####)は、このような構造で一つのテーブルを持っていることを好むだろう -

cp_properties: 
id(pkey), cid(foreign key to cp_def.cid) , code  date_issued date_expired 

しかし、あなたは設計のために、このクエリを試してみてください -

SELECT GROUP_CONCAT(CONCAT('SELECT code, date_expired FROM mydatabase.cp_', cid, ' WHERE DATE(date_issued) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)') SEPARATOR '\r\nUNION ALL\r\n') FROM mydatabase.cp_def 

このクエリは、UNION ALL句を含むSELECT文を生成し、生成されたクエリをprepared statementsで実行します。

EDIT

SELECT GROUP_CONCAT(CONCAT('SELECT code, date_expired FROM mydatabase.cp_', cid, ' WHERE DATE(date_issued) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)') SEPARATOR '\r\nUNION ALL\r\n') INTO @s FROM mydatabase.cp_def; 
PREPARE stmt FROM @s; 
EXECUTE stmt; 
DEALLOCATE PREPARE stmt; 
+0

これは、SQLステートメントの生成に完璧に機能する情報をありがとう。 準備されたステートメントの提案を使用しようとしましたが、準備されたステートメントを実行すると、SELECT GROUP_CONCATステートメントの結果が返されます。 'SELECT GROUP_CONCAT(CONCAT( 'SELECT code、date_expired FROM mydatabase.cp_ '、cid、' WHERE DATE(date_issued)= DATE_SUB(CURDATE()、INTERVAL 1 DAY) ')区切り文字'¥r¥nUNION ALL¥r¥n ')からFROM mydatabase.cp_def' – Andrew

+0

あなたが提供できる支援準備された声明をデザインするのを手伝ってくれたら大いに感謝します。 SET @s:= "SELECT GROUP_CONCAT(CONCAT( 'SELECT code、date_expired FROM mydatabase.cp_'、cid、 'WHERE DATE(date_issued)= DATE_SUB(CURDATE()、INTERVAL 1 DAY)は、 ')SEPARATOR' \ r \ nUNION ALL \ r \ n ')FROM mydatabase.cp_def "; PREPARE stmt FROM @s; EXECUTE stmt; – Andrew

+0

私は答えを更新しました。 – Devart

0

まず第一に、なぜcp_データは別々のテーブルに分割されましたか?データが適切に正規化されていれば、これは問題ではありません。

単純な解決策は、すべてのcp_テーブルの結合体のビューを作成することです - IMEでは、mysqlはビュー/サブクエリのプッシュ述語を効率的に最適化しません。そしてあなたが発見したように、あなたはまだその視点を維持する必要があります。

私は、Devartに記載されているソリューションの使用に至ります。あなたのデータを正規化するための代替物ではありません。それは決して効率的ではなく、テーブルの数が増えるほどパフォーマンスは急速に低下します。しかし、Devartは、手間をかけずに結果セットをどうやって取得するのかを簡単に突き止めました。短い答えはあなたができないということです。しかし、一致した行を一時表に挿入してから、その行を選択することができます。

0

私は解決策を見つけた:

保存UNION @sとテーブルの組み合わせの結果を保存するビューを作成するには、テーブル上のすべてのクエリ。

Select group_concat(concat('select * from new_schema.', name) separator '\r\nUNION 
ALL\r\n') 
into @s from new_schema.tempTableName; 
set @v = concat('create View view as ', @s); 
PREPARE stmt FROM @v; 
EXECUTE stmt; 
DEALLOCATE PREPARE stmt; 
関連する問題