【问题标题】:Which is more efficient: a SQL JOIN or nested PHP loop?哪个更有效:SQL JOIN 或嵌套 PHP 循环?
【发布时间】:2011-11-04 17:50:58
【问题描述】:

我有几个表需要显示数据。

Schools
-------
id | Title

Programs
--------
id | descr | title | type | school.id

当然,不是最好的设置,但我对数据库结构无能为力。

我需要创建一个列表,按学校、课程和课程类型分隔。现在,我有一个巨大的嵌套循环(伪代码):

Select * from Schools
For Each School
    print $school_header;
    Select Program Type from Programs WHERE School.id = $school_id 
        For Each Program type
           print $type_header;
           Select * from Programs where School.id = $school_id and type = $program_type
           For Each Program
               print $program_link;

不用说这是一团糟。

最终结果是一个列表:

  • 程序 1
    • 程序类型 1
      • 程序
      • 程序
    • 程序类型 2
      • 程序
      • 程序
    • 程序类型 3
      • 程序

有没有一种方法可以通过更少的查询和更少的代码而不是数据库密集型来做到这一点?

【问题讨论】:

    标签: php sql join while-loop nested-loops


    【解决方案1】:

    MSSQL 用于执行连接。此外,如果运气好的话,您的表可能会被索引,这将进一步提高性能。

    (很可能)运行一个复杂的查询总是比使用 php 循环遍历所有数据要好。

    编辑:

    也许您可以使用别名来标记数据的结构。
    示例:SELECT id as test_id .... SELECT program as test_test2_program...

    【讨论】:

    • 好的,我知道 JOINS。但是后来我得到了一个数组,其中所有内容都只有一行,没有嵌套。我必须能够在每个之前和之后执行开始和结束标记,这就是为什么我现在将它作为 PHP 嵌套循环。如果我需要为每件事做一个显示,那么使用 JOIN 是有意义的,但我不确定如果没有示例我还能在这里做什么。
    • @Oranges13 更新了我的答案,希望对您有所帮助。
    【解决方案2】:

    这里真正的问题不是一种或另一种编程语言是否更有效。性能上的巨大差异是由于数据局部性造成的,即在数据库本身上执行查询不需要您通过网络来回移动所有数据以进行评估,而 PHP 解决方案则需要。

    对于您的查询,您要做的是编写一个存储过程,该过程返回多个结果集(用于进一步加入 PHP)或单个大型结果集(通过加入 SQL)。我的猜测是它看起来像:

    SELECT S.Title as School_Title, pt.title as Program_type_title, p.title as Program_Title
    FROM School S 
    INNER JOIN ProgramType pt on s.id = pt.school_id
    INNER JOIN Program p on pt.id = p.program_type_id
    ORDER BY S.Title, pt.title, p.title
    

    这将为您提供大矩形数组,按每个标题按优先级排序。这样,您可以遍历行,直到看到 School 标题更改或 Program Type 标题更改或其他任何内容,然后呈现适当的结束标记。

    【讨论】:

    • 谢谢,查询并不是最大的问题。我仍然需要一种将列表嵌套在 PHP 中的方法。如果我有一个大数组,我不能这样做。我怎么知道某物何时是其他物的孩子?我如何知道何时打开或关闭某个部分的标签?
    • 跟踪定义组的每个列中看到的最后一个值。当当前值 != 最后一个值时,是时候渲染一些结束标签和一些新的开始标签了。
    • @Oranges - 您的循环需要跟踪前一个值和当前值。当它们不同时,关闭该部分。在这方面,以 XML 形式回归可能会更简单。
    【解决方案3】:
    SELECT *
    FROM Schools
    INNER JOIN Programs
        ON Programs."school.id" = Schools.id
    INNER JOIN Groups
        ON Groups."programs.id" = Programs.id
    INNER JOIN GroupsToCourses
        ON GroupsToCourses.group_id = Groups.id
    INNER JOIN Courses
        ON Courses.course_id = GroupsToCourses.course_id
    

    它几乎肯定会胜过您在 PHP 中的代码,并且可以通过节省数据库往返、在线数据以及让数据库优化器完成其工作来显着胜过它。

    【讨论】:

    • 感谢 Cade - 我了解 JOINS。如果我使用连接,我需要关于如何获得我想要的输出的示例,因为这只会给我一个大的胖数组,而不是像我目前拥有的嵌套数组。
    • @Oranges13 嵌套可以在 SQL Server 中使用 WITH ROLLUP 或当您循环访问客户端代码中的(单个)集时完成,当发生变化以开始一个新组时才中断。
    【解决方案4】:

    MSSQL 会做得更好。它是如何设计 RDBMS 来处理这类事情的。如果您在 db 服务器上执行这些操作,则可以节省网络利用率。

    【讨论】:

    • 显然不是MySql。其余的都可以
    • 此外,数据库甚至可能不必执行 [完整] 嵌套循环即可获得相同的结果;即使它确实使用了许多循环,它通常也可以大大减小 N 的大小并选择“更好的顺序”。
    • 这很好,但这是 Microsoft SQL Server。
    • 问题是如何做到这一点。我了解加入。当我需要一个嵌套数组时,它给了我一个数组。
    • @Oranges13 嵌套可以在 SQL Server 中使用 WITH ROLLUP 完成,或者当您循环访问客户端代码中的(单个)集合时,只是在发生变化以开始新组时中断。
    猜你喜欢
    • 2014-07-11
    • 2017-03-11
    • 1970-01-01
    • 2013-09-19
    • 2022-07-18
    • 1970-01-01
    • 1970-01-01
    • 2017-08-11
    • 1970-01-01
    相关资源
    最近更新 更多