簡體   English   中英

MySql根據計數進行子選擇和計數

[英]MySql subselects and counts based on counts

這是我的表格結構模型。 三張桌子。

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

因此,在此示例中,未使用蘋果行進行計數,因為它不是動物,也不使用蝙蝠,因為它的狀態設置為否(表示不測量),並且僅使用了最近的測量確定計數。

我目前在現實生活中有一種解決方法,但是它沒有遵循良好的數據庫規范化。 在我的現實表中,我有一個current_meas列,該列在進行新測量並輸入到測量表中時會更新。 然后,我只需要使用前兩個表,並且我有一個SELECT語句和一堆使用IF的嵌入式SUM語句,例如,該值在0-9之間。 它確實提供了我想要的東西,但是我的應用已經發展到這種便利性在其他領域已成為問題。

因此,問題是,有沒有一種更優雅的方法可以在一句話中做到這一點? 子選擇? 臨時表? 獲取計數是該應用程序的核心。

這是一個基於PHP5,MySQL5,JQuery 1.8的webapp,以防給我更多選擇。 提前致謝。 我喜歡這個堆棧,希望能對我有所幫助。

這是一種方法

創建一個臨時表以獲取最近的測量值

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

根據建議的兩個答案,這是我最終要做的事情。

  1. 首先,我創建了一個臨時表,該表基於一種可能性(動物)生成狀態表,狀態為1(是)。
  2. 其次,我創建了一個臨時表,該表從第一個臨時表中生成了單個現實的表,並為每個表找到了最新的度量。
  3. 在第二張表中,我做了一個選擇,使我可以看到范圍內的計數明細。

當我僅使用一個臨時表進行嘗試時,每種可能性的查詢將花費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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM