2

これが私のテーブル構造のモデルです。3つのテーブル。

----------------     ----------------------------     -------------------------------
|possibilities |     |realities                 |     |measurements                 |
|--------------|     |--------------------------|     |-----------------------------|
|pid| category |     |rid | pid | item | status |     |mid | rid | meas | date      |
|--------------|     |--------------------------|     |-----------------------------|
|1  | animal   |     |1   | 1   | dog  | 1 (yes)|     |1   | 1   | 3    | 2012-01-01|
|2  | vegetable|     |2   | 1   | fox  | 1      |     |2   | 3   | 2    | 2012-01-05|
|3  | mineral  |     |3   | 1   | cat  | 1      |     |3   | 1   | 13   | 2012-02-02|
----------------     |4   | 2   | apple| 2 (no) |     |4   | 3   | 24   | 2012-02-15|
                     |5   | 1   | mouse| 1      |     |5   | 2   | 5    | 2012-02-16|
                     |7   | 1   | bat  | 2      |     |6   | 6   | 4    | 2012-02-17|
                     ----------------------------     -------------------------------

私が求めているのは、関連する「現実」のステータスが1(現在追跡されていることを意味する)である「可能性」テーブルの特定のエントリの測定範囲に基づいた一連のカウントを表示する結果ですが、関連する唯一の測定値は最新のものです。

これは私が可能性として動物を使用して探している結果の例です。

-----------------------
| 0-9 | 10-19 | 20-29 |
|---------------------|
| 2   | 1     | 1     |
-----------------------

したがって、この例では、リンゴの列は動物ではないためカウントに使用されませんでした。また、ステータスがno(測定しないことを意味する)に設定されているためコウモリも使用されず、最新の測定値のみが使用されました。カウントを決定します。

現在、実際の使用で回避策がありますが、データベースの正規化が適切に行われていません。私の現実のテーブルには、新しい測定値が取得されて測定値テーブルに入力されたときに更新されるcurrent_meas列があります。次に、最初の2つのテーブルのみを使用する必要があり、たとえば、値が0〜9のIFを使用する一連の埋め込みSUMステートメントを含む単一のSELECTステートメントがあります。それは私が欲しいものを正確に与えてくれますが、私のアプリはこの便利さが他の分野で問題になっているところまで進化しました。

それで、問題は、1つのステートメントでこれを行うためのよりエレガントな方法がありますか?副選択?一時テーブル?カウントを取得することは、アプリが何であるかの中核です。

これは、PHP5、MySQL5、JQuery 1.8ベースのWebアプリであり、さらにいくつかのオプションがあります。前もって感謝します。私はスタックが大好きで、それが私を助けてくれたのと同じくらい助けてくれることを望んでいます。

4

2 に答える 2

0

これが1つのアプローチです

最近の測定値を取得するための一時テーブルを作成します

CREATE TEMPORARY TABLE RecentMeasurements
SELECT * FROM Measurements m
INNER JOIN (SELECT max(mid) max_id,date FROM Measurements GROUP BY DATE ORDER BY DATE ) x
ON x.max_id=m.mid

次に、クエリを実行しますか?

SELECT *, your counting logic
FROM Realities
WHERE status = 1 AND pid = 1
INNER JOIN RecentMeasurements
于 2012-05-14T16:26:44.830 に答える
0

これが私が提案した2つの答えに基づいてやったことです。

  1. 最初に、1つの可能性(動物)に基づいており、ステータスが1(はい)である現実のテーブルを生成する一時テーブルを作成しました。
  2. 次に、最初の一時テーブルから個々の現実のテーブルを生成し、それぞれの最新の測定値を見つける一時テーブルを作成しました。
  3. この2番目の表から、範囲内のカウントの内訳を示す選択を行います。

一時テーブルを1つだけ使用して試してみると、クエリは可能性ごとに5〜10秒かかります。私の実際の使用では、現在30の可能性(スクリプトがそれぞれをループしてこれらの一時テーブルを生成して選択する)、1,000をはるかに超える現実(任意の日にアクティブな600、月に100を追加)、および21,000を超える測定(毎日20-30追加)。それは私にはうまくいきませんでした。したがって、それをより小さなプールに分割して、3〜4秒以内に実行されるレポート全体に縮小します。

これが私の実際のテーブルと列の名前を持つMySQLのものです。

//Delete the temporary tables in advance
$delete_np_prod = 'DROP TABLE IF EXISTS np_infreppool';
mysql_query($delete_np_prod) or die ("Drop NP Prod Error " . mysql_error ());
$delete_np_max = 'DROP TABLE IF EXISTS np_maxbrixes';
mysql_query($delete_np_max) or die ("Drop NP Max Error " . mysql_error ());

//Make a temporary table to hold the totes of this product at North Plains that are active
$create_np_prod_pool_statement = 'CREATE TEMPORARY TABLE np_infreppool
SELECT inf_row_id FROM infusion WHERE formid = ' . $active_formids["formid"] . ' AND location = 1 AND status = 1';
mysql_query($create_np_prod_pool_statement) or die ("Prod Error " . mysql_error ());

//Make a temporary table to hold the tote with its most recent brix value attached to it.
$create_np_maxbrix_pool_statement = 'CREATE TEMPORARY TABLE np_maxbrixes
SELECT b.inf_row_id AS inf_row_id, b.brix AS brix from brix b, np_infreppool pool WHERE b.inf_row_id = pool.inf_row_id AND b.capture_date = (SELECT max(capture_date) FROM brix WHERE inf_row_id = pool.inf_row_id )';
mysql_query($create_np_maxbrix_pool_statement) or die ("Brix Error " . mysql_error ());

//Get the counts for slected form from NP
$get_report_np = "SELECT 
        SUM(IF(brix BETWEEN 0 AND 4,1,0)) as '0-4',
        SUM(IF(brix BETWEEN 5 AND 9,1,0)) as '5-9',
        SUM(IF(brix BETWEEN 10 AND 14,1,0)) as '10-14',
        SUM(IF(brix BETWEEN 15 AND 19,1,0)) as '15-19',
        SUM(IF(brix BETWEEN 20 AND 24,1,0)) as '20-24',
        SUM(IF(brix BETWEEN 25 AND 29,1,0)) as '25-29',
        SUM(IF(brix BETWEEN 30 AND 34,1,0)) as '30-34',
        SUM(IF(brix BETWEEN 35 AND 39,1,0)) as '35-39',
        SUM(IF(brix BETWEEN 40 AND 44,1,0)) as '40-44',
        SUM(IF(brix BETWEEN 45 AND 49,1,0)) as '45-49',
        SUM(IF(brix BETWEEN 50 AND 54,1,0)) as '50-54',
        SUM(IF(brix BETWEEN 55 AND 59,1,0)) as '54-49',
        SUM(IF(brix BETWEEN 60 AND 64,1,0)) as '60-64',
        SUM(IF(brix BETWEEN 65 AND 69,1,0)) as '65-69',
        SUM(IF(brix >=70, 1, 0)) as 'Over 70'
    FROM np_maxbrixes";
$do_get_report_np = mysql_query($get_report_np);
$got_report_np = mysql_fetch_array($do_get_report_np);

アップデート

一時テーブルを使用せずに単一のSELECTステートメントで機能するようになり、より高速に機能します。上記のサンプルスキーマを使用すると、次のようになります。

    SELECT 
    SUM(IF(m.meas BETWEEN 0 AND 4,1,0)) as '0-4',
    SUM(IF(m.meas BETWEEN 5 AND 9,1,0)) as '5-9',
    SUM(IF(m.meas BETWEEN 10 AND 14,1,0)) as '10-14',
    SUM(IF(m.meas BETWEEN 15 AND 19,1,0)) as '15-19',
    SUM(IF(m.meas BETWEEN 20 AND 24,1,0)) as '20-24',
    SUM(IF(m.meas BETWEEN 25 AND 29,1,0)) as '25-29',
    SUM(IF(m.meas BETWEEN 30 AND 34,1,0)) as '30-34',
    SUM(IF(m.meas BETWEEN 35 AND 39,1,0)) as '35-39',
    SUM(IF(m.meas BETWEEN 40 AND 44,1,0)) as '40-44',
    SUM(IF(m.meas BETWEEN 45 AND 49,1,0)) as '45-49',
    SUM(IF(m.meas BETWEEN 50 AND 54,1,0)) as '50-54',
    SUM(IF(m.meas BETWEEN 55 AND 59,1,0)) as '54-49',
    SUM(IF(m.meas BETWEEN 60 AND 64,1,0)) as '60-64',
    SUM(IF(m.meas BETWEEN 65 AND 69,1,0)) as '65-69',
    SUM(IF(m.meas >=70, 1, 0)) as 'Over 70'
FROM measurement m, realities r 
WHERE r.status = 1 AND r.pid = " . $_GET['pid'] . " AND r.rid = m.rid AND m.date = (SELECT max(date) FROM measurements WHERE rid = r.rid)
于 2012-05-15T13:50:39.100 に答える