这是我的表结构的模型。三张桌子。
---------------- ---------------------------- -------------------------------
|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,以防万一给我一些选择。提前致谢。我喜欢这个堆栈,希望尽可能多地帮助我。
答案 0 :(得分:0)
这是一种方法
创建临时表以获取最近的测量结果
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 :(得分:0)
根据建议的两个答案,这是我最终做的事情。
当我尝试使用一个临时表时,查询每个可能性需要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)