我在数据库中有4个表格,可以让我管理一种“检查清单”。对于每个pathology
,只需几句话,我就有一大步(process
)分为tasks
的倍数。所有这些都与摘要表中的特定操作(progress.case_id
)相关联。
database.pathology
+--------------+------------+
| id_pathology | name |
+--------------+------------+
| 1 | Pathology1 |
| 2 | Pathology2 |
| 3 | Pathology3 |
+--------------+------------+
database.process
+------------+----------+--------------+----------------+
| id_process | name | pathology_id | days_allocated |
+------------+----------+--------------+----------------+
| 1 | BigTask1 | 2 | 5 |
| 2 | BigTask2 | 2 | 3 |
| 3 | BigTask3 | 2 | 6 |
| ... | ... | ... | ... |
+------------+----------+--------------+----------------+
database.task
+---------+-------+------------+
| id_task | name | process_id |
+---------+-------+------------+
| 1 | Task1 | 1 |
| 2 | Task2 | 1 |
| 3 | Task3 | 1 |
| 4 | Task4 | 2 |
| ... | ... | ... |
+---------+-------+------------+
database.progress
+-------------+---------+---------+---------+------------+---------+
| id_progress | task_id | case_id | user_id | date | current |
+-------------+---------+---------+---------+------------+---------+
| 1 | 1 | 120 | 2 | 2015-11-02 | 1 |
| 2 | 2 | 120 | 2 | 2015-11-02 | 0 |
| 3 | 1 | 121 | 3 | 2015-11-02 | 1 |
+-------------+---------+---------+---------+------------+---------+
我必须展示类似的东西
我的问题是:最有效的方法是什么?
查询只有一个表(进度)显示最多,然后查询另一个表以获取不同进程和天数的名称更快吗?
也许联合功能更有效率?
或者您认为我的数据库结构不合适吗?
对于每种情况,我们可以执行大约50个任务,将当前字段转换为复选框。后台脚本也在运行。它根据剩余天数分析提供的天数,以确定此特定案例是否可能有延迟。
对于每种情况,进度表已经填充了与案例病理相关的所有任务。目前的领域始终是' 0'在开始。
我已经尝试了多种内容,例如
$result = $db->prepare("SELECT DISTINCT process_id,process.name FROM task, progress,process WHERE progress.task_id = task.id_task AND task.process_id = process.id_process AND progress.case_id = ?");
$result->execute(array($id));
foreach($result as $row)
{
echo "<b>".$row[1]."</b><br>";
$result = $db->prepare("SELECT name,id_task FROM task WHERE process_id = ?");
$result->execute(array($row[0]));
foreach($result as $row)
{
echo $row[0];
$result = $db->prepare("SELECT user_id, date, current FROM progress WHERE progress.task_id = ? AND case_id = ?");
$result->execute(array($row[1], $id));
foreach($result as $row)
{
if($row[2] == 0)
{echo "<input type='checkbox' />";}
else
{
echo "<input type='checkbox' checked/>";
echo "user : ".$row[0]." date : ".$row[1]."<br>";
}
}
}
但我很确定我做得不对。我应该更改我的数据库基础我应该使用特定的MySQL技巧吗?或者只是一个更有效的PHP处理?
答案 0 :(得分:3)
就效率而言,数据库查询是您可以执行的最慢操作之一。您可以采取的任何措施来减少您的查询数量,这将大大有助于您的应用程序更快。
但更重要的是,您的应用程序需要按设计工作,这意味着开发人员需要了解正在发生的事情,数据不应该只是等待被覆盖,以及初级开发人员将在3年内负责维护这项工作,并不想将头发撕掉。
速度比慢速好。
慢慢胜过破碎。
对于您的特定问题,如果可能,永远不会在循环内部进行查询。特别是当该循环由从同一数据库中提取的数据控制时。这是一种代码气味,需要正确使用JOIN
s。
对SQL Join Diagrams的Google图片搜索显示了大量维恩图,其中显示了每个JOIN
返回的不同类型的数据。如有疑问,通常需要LEFT JOIN
s。
所以,让我们确定你的关系:
病理学
过程
任务
进度
案例
用户
基于此表结构,我们的主要分组将是Case,Pathology和User。
也就是说,如果您是登录用户,并且想要按案例查看进度,则可能需要查看以下内容:
Case 110:
Pathology1:
BigTask1:
Task1: X
Task2: []
BigTask2:
Task3: X
Pathology2:
BigTask3:
Task4: []
Case 120:
Pathology1:
BigTask1:
Task1: []
我们希望用户ID == 1; 我们的第一次排序将基于Case 我们的第二次排序将基于病理学 我们的第三次排序将基于Process 我们最后的排序将是在任务...
因此,获得上述结果的数据将是:
+------+------------+----------+-------+----------+
| case | pathology | process | task | progress |
+------+------------+----------+-------+----------+
| 110 | Pathology1 | BigTask1 | Task1 | 1 |
| 110 | Pathology1 | BigTask1 | Task2 | 0 |
| 110 | Pathology1 | BigTask2 | Task3 | 1 |
| 110 | Pathology2 | BigTask3 | Task4 | 0 |
| 120 | Pathology1 | BigTask1 | Task1 | 0 |
+------+------------+----------+-------+----------+
我们的订购&#39;子句是从最后到第一个...... ORDER BY task, process, pathology, case
...我们可以用PHP对它进行排序,但数据库比我们更好。如果您的索引设置正确,数据库可能甚至不需要排序,它只是按顺序获取它。
获取特定用户的上述数据的查询是:
SELECT
prog.case_id AS case,
path.name AS pathology,
proc.name AS process,
task.name AS task,
prog.current AS progress
FROM
pathology path
LEFT JOIN process proc ON path.id_pathology = proc.pathology_id
LEFT JOIN task ON task.process_id = proc.id_process
LEFT JOIN progress prog ON task.id_task = prog.task_id
WHERE prog.user_id = :userid
ORDER BY task, process, pathology, case
您的PHP可能就是
<?php
$sql = <<<EOSQL
SELECT
prog.case_id AS case,
path.name AS pathology,
proc.name AS process,
task.name AS task,
prog.current AS progress
FROM
pathology path
LEFT JOIN process proc ON path.id_pathology = proc.pathology_id
LEFT JOIN task ON task.process_id = proc.id_process
LEFT JOIN progress prog ON task.id_task = prog.task_id
WHERE prog.user_id = :userid
ORDER BY task, process, pathology, case
EOSQL;
$result = $db->prepare($sql);
$result->execute(array(':userid' => $id));
$rows = $result->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
var_dump($row);
// array(5) {
// ["case"]=>
// int(110)
// ["pathology"]=>
// string(10) "Pathology1"
// ["process"]=>
// string(8) "BigTask1"
// ["task"]=>
// string(5) "Task1"
// ["progress"]=>
// int(1)
// }
}