草庐IT

php - MySQL查询数据库以显示检查列表的最佳方式

coder 2023-10-20 原文

我在一个数据库中有 4 个表,可以让我管理一种“核对表”。对于每个病理学,我有一个很大的步骤(过程)分成多个任务。所有这些都链接到汇总表中的特定操作 (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 处理?

最佳答案

就效率而言,数据库查询是您可以执行的最慢的操作之一。您可以采取任何措施来减少查询次数,这将大大有助于加快您的应用程序速度。

但比这更重要的是,您的应用程序需要按设计工作,这意味着开发人员需要了解正在发生的事情,数据不应该只是等待被覆盖,而初级开发人员将被分配任务在 3 年内保持这种状态不会想撕掉他们的头发。

快总比慢好。

慢总比坏好。

对于您的特定问题,如果可能的话,永远不要在循环内进行查询。特别是当该循环由您从同一数据库中提取的数据控制时。这是一种代码味道,需要正确使用 JOIN

Google 图片搜索 SQL Join Diagrams显示了大量维恩图示例,这些示例显示了每个 JOIN 返回的不同类型的数据。如有疑问,您通常需要 LEFT JOIN

那么,让我们确定您的关系:

  • 病理学

    • 未在您的结果中使用。
    • 找到一种方法将其合并到您的查询中,因为“Pathology2”出现在您的模型中。
  • 过程

    • 一对多关系中的引用病理学。每个进程可以有一个病理,但每个病理可以有 0 个或多个进程。
  • 任务

    • 一对多关系中的引用任务。任务包含进程的子进程。
  • 进步

    • 引用任务,以及未显示的案例和用户。当引用特定案例和用户时,进度似乎是任务的详细信息。
    • 我假设存在一个业务约束,其中 task_id、case_id 和 user_id 必须是唯一的...也就是说,用户 1 只能有 1 个任务 1 和案例 100 的进度条目。
    • 除了保存任务的详细信息外,还充当任务、案例和用户之间的桥梁,为这三个表提供多对多关系。由于 Task 是 Process 的直接子项,而 Process 是 Pathology 的直接子项,因此它与 Pathology 之间存在多对多关系。
  • 案例

    • 推断存在此表。
    • 由任务引用。
  • 用户

    • 推断存在此表。
    • 由任务引用。

基于此表结构,我们的主要分组将是案例、病理学和用户。

也就是说,如果您是登录用户并且想按案例查看您的进度,您会希望看到以下内容:

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”子句是从最后到第一...比我们如果您的索引设置正确,数据库甚至可能不必对内容进行排序,它只会按顺序获取内容。

为特定用户获取上述数据的查询是:

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)
    // }
}

关于php - MySQL查询数据库以显示检查列表的最佳方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33481362/

有关php - MySQL查询数据库以显示检查列表的最佳方式的更多相关文章

  1. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  2. ruby-on-rails - Rails 编辑表单不显示嵌套项 - 2

    我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib

  3. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  4. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  5. ruby - RVM 使用列表[0] - 2

    是否有类似“RVMuse1”或“RVMuselist[0]”之类的内容而不是键入整个版本号。在任何时候,我们都会看到一个可能包含5个或更多ruby的列表,我们可以轻松地键入一个数字而不是X.X.X。这也有助于rvmgemset。 最佳答案 这在RVM2.0中是可能的=>https://docs.google.com/document/d/1xW9GeEpLOWPcddDg_hOPvK4oeLxJmU3Q5FiCNT7nTAc/edit?usp=sharing-知道链接的任何人都可以发表评论

  6. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

    所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

  7. ruby-on-rails - link_to 不显示任何 rails - 2

    我试图在索引页中创建一个超链接,但它没有显示,也没有给出任何错误。这是我的index.html.erb代码。ListingarticlesTitleTextssss我检查了我的路线,我认为它们也没有问题。PrefixVerbURIPatternController#Actionwelcome_indexGET/welcome/index(.:format)welcome#indexarticlesGET/articles(.:format)articles#indexPOST/articles(.:format)articles#createnew_articleGET/article

  8. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

    我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

  9. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

  10. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

随机推荐