【问题标题】:How to do pagination, when the number of returned rows from sql is altered in php?当从 sql 返回的行数在 php 中发生更改时,如何进行分页?
【发布时间】:2012-11-26 07:12:23
【问题描述】:

我有一个数据库,其中有一个 books 表和一个 people 表,每个表大约有 100k 个条目。第三个表将两者连接起来,因此它们具有多对多关系。除了 book 和 person id 的列之外,连接表还有一个列,指示 book 与 person、fx writer、co-writer 或 publisher 或其他东西之间的关系类型。

我需要进行查询,以返回所有书籍条目的列表,其中包含与之相关的人员和特定的关系类型。连接这两个表时,SQL 会返回多行记录与多个人相关的书籍,因此我随后在 php 中对其进行了排序。与书籍相关的人数因书籍而异,没有可预测的模式。

我需要做一个分页系统。

在这种情况下,最聪明的分页方式是什么?

【问题讨论】:

  • 你是给书分页还是给人物分页?
  • 哦,忘了说,我正在给书分页。
  • 我强烈怀疑您必须在不加入人员的情况下选择书籍,以便您可以在分页中正确限制并执行单独的查询来选择人员。
  • 谢谢!所以一个解决方案是进行两个查询,一个来计算书籍,一个连接表格并获取信息以填充列表?
  • 是的。我已经在答案中写出来了

标签: php sql pagination


【解决方案1】:

您可以使用group_concat 在一行中选择每本书的所有相关人员,然后使用limit offset, num_rows 对结果集进行分页

select b.book_id, b.title, ..., group_concat(c.type), group_concat(p.name)
from books b
join connections c on c.book_id = b.book_id
join persons p on p.person_id = c.person_id
group by book_id
limit 100, 50

【讨论】:

    【解决方案2】:

    你有几种选择,我想说它们可以分为两组

    1. 您发送了所有行并使用纯 JavaScript 进行分页(在客户端)
    2. 除了您在 sql 查询中指定的限制之外,您还指定了一个偏移量。该偏移量存储在您的 php 会话中,并且每次用户在您的分页中选择下一个/上一个时递增/递减。

    优点/缺点:

    1. 每个会话一个单一的 sql 查询,没有额外的 http 请求,因为所有都在客户端内部处理。当查看结果时服务器端发生变化时,可视化的结果可能会过时。传输的行数更大,因此第一个可视化的加载时间更长。

    2. 仅查询和处理单个视图实际需要的那些行。更多行仅应请求检索。行始终是最新的,但是如果您使用偏移值而同时行数发生变化(极少数情况),事情可能会变得令人讨厌。每个下一个/上一个操作一个 http 请求,但单个视图的加载时间更快。


    对于由于join导致单书多次点击的问题:

    我认为你应该在这里采取不同的策略:

    1. 您可以使用子查询(查询中的查询),这样您就可以为内部查询指定偏移量和限制,仅在不考虑人员的情况下检索书籍。然后外部查询将人员连接到内部查询的结果。

    2. 不要为与书关联的多个人检索单独的行,而是将这些命中分组并通过连接他们的姓名或其他方式加入这些人。就像您检索的每本书中的一组人一样。这样你就可以毫无问题地指定偏移量和限制。

    【讨论】:

    • 我认为第一个问题是左加入人们每本书会产生多个结果。
    • 感谢您的回答。是的,问题是,我不能在 SQL 中使用 LIMIT/OFFSET 组合,因为我无法预测 OFFSET 应该是什么值。
    • @krismeld:我不能跟着你。 offset 的值仅取决于会话导航。您从 0(零)开始,并为每个“下一步”操作添加页面大小(例如 20)。为什么你不能确定?请注意,偏移量与您从数据库中获得的命中总数无关。
    • @popnoodles:我也为这个问题添加了注释,谢谢提示!
    【解决方案3】:

    你需要选择你的书没有离开加入人们,这样你就可以使用 LIMIT 0,20 用于第 1 页,LIMIT 20,20 用于第 2 页等用于分页

    然后分别获取每本书的人员列表。您可以对每本书使用一次 SQL 调用,也可以将所有选定的书籍全部获取并修改该列表,以更快者为准。

    【讨论】:

      【解决方案4】:

      这是一种糟糕的形式,因为您很可能应该按照前面的答案所建议的那样去做——在 SQL 中工作。 但是,您发表评论说您在 PHP 中全力以赴。 也就是说,如果您在脚本中有所有结果(即不是一个巨大的数据库结果),那么可以很容易地在 PHP 中处理它。

      1. 将结果存储在 $_SESSION 变量中。
      2. 计算结果的长度。
      3. 将结果除以每页的项目数。
      4. for 循环显示第一页项目的结果。
      5. 建立一个链接,将页码与查询字符串或其他方式一起传递..
      6. for 循环从下一页的下一项开始的结果等。

      您可能对PHP.net manual page for count(). 上提供的一些自定义功能感兴趣

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-09-21
        • 1970-01-01
        • 2011-01-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多