Php MySQL查询数据库以显示检查列表的最佳方式
我在一个数据库中有4个表,允许我管理一种“检查表”。对于每个Php MySQL查询数据库以显示检查列表的最佳方式,php,mysql,database,performance,Php,Mysql,Database,Performance,我在一个数据库中有4个表,允许我管理一种“检查表”。对于每个病理学,我有一大步(过程)被分解为多个任务。所有这些都链接到摘要表中的特定操作(progress.case\u id) database.pathology +--------------+------------+ | id_pathology | name | +--------------+------------+ | 1 | Pathology1 | | 2 | Path
病理学
,我有一大步(过程
)被分解为多个任务
。所有这些都链接到摘要表中的特定操作(progress.case\u 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>";
}
}
}
$result=$db->prepare(“从任务、进度、流程中选择不同的流程\u id、流程.name,其中progress.task\u id=task.id\u task和task.process\u id=process.id\u流程和progress.case\u id=?”;
$result->execute(数组($id));
foreach($结果为$行)
{
回显“.”行[1]。“
”;
$result=$db->prepare(“从任务中选择名称、id\u任务,其中进程id=?”;
$result->execute(数组($row[0]);
foreach($结果为$行)
{
echo$行[0];
$result=$db->prepare(“从progress.task_id=?和case_id=?的进度中选择user_id、date、current FROM progress”);
$result->execute(数组($row[1],$id));
foreach($结果为$行)
{
如果($row[2]==0)
{echo”“;}
其他的
{
回声“;
回显“用户:.$行[0]”。日期:.$行[1]”。
;
}
}
}
但是我很确定我做得不对。我应该改变我的数据库基础设施吗?我应该使用特定的MySQL技巧吗?或者可能只是更高效的PHP处理吗?就效率而言,数据库查询是您可以执行的最慢的操作之一。您可以做些什么来减少需要执行的查询数量您的make将大大加快应用程序的速度 但更重要的是,您的应用程序需要按设计工作,这意味着开发人员需要了解正在发生的事情,数据不应该只是等待被覆盖,而负责在3年内维护这些数据的初级开发人员也不想把他们的头发扯掉 快总比慢好 慢总比坏好 对于您的特定问题,如果可能的话,不要在循环内进行查询。特别是当循环由您从同一数据库提取的数据控制时。这是一种代码气味,需要正确使用
JOIN
s
Google图像搜索显示了大量的Venn图示例,这些图显示了每个连接返回的不同类型的数据。如果有疑问,通常需要左连接
因此,让我们确定您的关系:
- 病理学
- 未在结果中使用
- 找到一种方法将其合并到您的查询中,因为“病理学2”出现在您的模型中
- 过程
- 以一对多关系引用病理学。每个过程可以有一个病理学,但每个病理学可以有0个或多个过程
- 任务
- 引用一对多关系中的任务。任务包含进程的子进程
- 进展
- 引用任务以及未显示的案例和用户。进度似乎是引用特定案例和用户时任务的详细信息
- 我假设存在一个业务约束,其中task_id、case_id和user_id必须是唯一的……也就是说,对于task 1和case 100,user 1只能有一个进度条目
- 除了保存任务的详细信息外,它还充当任务、案例和用户之间的桥梁,为三个表提供多对多关系。由于任务是过程的直接子级,而过程是病理学的直接子级,因此它为病理学提供了多对多关系
- 案例
- 推断此表是否存在
- 由任务引用
- 使用者
- 推断此表是否存在
- 由任务引用
基于此表结构,我们的主要分组将是病例、病理学和用户
也就是说,如果您是一个登录用户,并且希望按情况查看进度,您将希望看到以下内容:
Case 110:
Pathology1:
BigTask1:
Task1: X
Task2: []
BigTask2:
Task3: X
Pathology2:
BigTask3:
Task4: []
Case 120:
Pathology1:
BigTask1:
Task1: []
我们希望用户ID==1;
我们的第一次分类将基于案例
我们的第二个分类将基于病理学
我们的第三个排序将基于流程
我们的最后一次分拣任务是
因此,获得上述结果的数据为:
+------+------------+----------+-------+----------+
| 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 |
+------+------------+----------+-------+----------+
我们的“ORDER BY”子句从头到尾…按任务、过程、病理学、病例排序
…我们可以用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)
// }
}
嵌套查询,其中内部查询使用来自外部查询的数据,几乎总是可以更好地编写为单个联接ed查询。要添加@MarcB的注释,您应该将嵌套查询识别为软件开发反模式。您应该始终寻找替代方法