【问题标题】:How should I Query this in mysql我应该如何在mysql中查询这个
【发布时间】:2015-04-07 03:02:01
【问题描述】:

我有一个网络应用程序,我在其中显示了基于此表架构的一系列帖子(有数千行这样的行和其他列也有(因为这个问题不需要删除)):-

+---------+----------+----------+
|   ID    |   COL1   |   COL2   |
+---------+----------+----------+
|   1     |    NULL  |   ----   |
|   2     |    ---   |   NULL   |
|   3     |    NULL  |   ----   |
|   4     |    ---   |   NULL   |
|   5     |    NULL  |   NULL   |
|   6     |    ---   |   NULL   |
|   7     |    NULL  |   ----   |
|   8     |    ---   |   NULL   |
+---------+----------+----------+

我使用这个查询:-

SELECT * from `TABLE` WHERE `COL1` IS NOT NULL AND `COL2` IS NULL ORDER BY `COL1`;

我得到的结果集是这样的:-

+---------+----------+----------+
|   ID    |   COL1   |   COL2   |
+---------+----------+----------+
|   12    |    ---   |   NULL   |
|   1     |    ---   |   NULL   |
|   6     |    ---   |   NULL   |
|   8     |    ---   |   NULL   |
|  11     |    ---   |   NULL   |
|  13     |    ---   |   NULL   |
|   5     |    ---   |   NULL   |
|   9     |    ---   |   NULL   |
|   17    |    ---   |   NULL   |
|   21    |    ---   |   NULL   |
|   23    |    ---   |   NULL   |
|   4     |    ---   |   NULL   |
|   32    |    ---   |   NULL   |
|   58    |    ---   |   NULL   |
|   61    |    ---   |   NULL   |
|   43    |    ---   |   NULL   |
+---------+----------+----------+

请注意,由于 order by 子句,IDs 列是混乱的。

我有适当的索引来优化这些查询。 现在,让我解释一下真正的问题。我的网络应用程序中有一种延迟加载功能。因此,我在第一页查询后使用LIMIT 10 每页显示大约 10 个帖子。

到目前为止,我们都很好。但是,真正的问题出现在我必须加载第二页时。我现在要查询什么?我不希望帖子被重复。几乎每 15 秒就会有新帖子出现,这使它们位于结果集的顶部(我的字面意思是第一行)(我不想在第二页或第三页显示这些最新帖子,但它们会改变结果集大小,所以我不能在第二页使用LIMIT 10,10,以此类推,因为帖子将被重复。)。

现在,我只知道我显示的帖子的最后一个 ID。在这里说21。所以,我想显示 ID 为 23,4,32,58,61,43 的帖子(请参阅上面的结果集表)。现在,我是否在不使用 LIMIT 子句的情况下加载所有行并显示出现在 id 21 之后的 10 个 id。但为此,我将不得不对数千个无用的行进行交互。但是,我不能在第 2、3... 页使用 LIMIT 子句,这是肯定的。另外,ID很乱,所以我绝对不能使用WHERE ID>...。那么,我们现在要去哪里?

【问题讨论】:

  • 既然你的COL1是可排序的,那么在每个请求中记住COL1的最新记录如何,在下一页加载WHERE COL1>?
  • @Passerby,我已经想到了。但是,COL1 有许多相同的行。实际上,COL1 是一个时间戳,许多行可能具有相同的时间戳(在我的结果集中)

标签: php mysql sql


【解决方案1】:

我不确定我是否正确理解了您的问题,但我认为我会这样做:

  • 在表中添加时间戳列,我们称之为date_added
  • 显示首页时,按原样使用您的查询(使用LIMIT 10)并保留最新记录的时间戳;我们就叫它last_date_added吧。
  • 对于第 2、3 及后续页面,修改查询以过滤掉所有带有date_added > last_date_added 的记录,并使用LIMIT 10, 10LIMIT 20, 10LIMIT 30, 10 等。

这会及时冻结您的结果集,并在每次访问第一页时重置它。

注意事项:

  • 根据结果集的顺序,您可能需要一个单独的查询来获取last_date_added。或者,您也可以在当前时间截断,即访问第一页的时间。
  • 如果您的 ID 是连续的,您可以对 ID 使用相同的技巧。

【讨论】:

  • 有趣的是,COL1 列是时间戳。但是,不幸的是,正如我在上面的评论中提到的,它并不是很独特,因为许多行共享相同的时间戳。我检查帖子是否符合标准并将COL1 从 NULL 更改为当前时间戳。因此,如果许多帖子符合条件,则它们具有相同的时间戳。
  • @user4647309 那么为什么不添加一个额外的date_added 时间戳,在插入记录时设置呢?如果您使用微秒精度,它应该是相当独特的。或者,正如我所说,如果您的 ID 是连续的,那么在执行第一页的查询之前,您可以获得最高的 ID 并使用它来冻结后续页面的结果集。
  • @RobbyCornelissen 我认为问题在于按COL1 排序会“破坏”ID 或任何类似事物的排序顺序:使用相同的COL1 这可能会有所帮助,但是@ 987654335@ 也会过滤掉一些COL1 更高但ID 更低的结果。
  • @Passerby 感谢您的反馈。我想我还没有完全理解 OP 实际上想要实现的目标。但是,似乎一个答案被接受了,所以我很高兴有人这样做了:-)
【解决方案2】:

嗯.. 我想了一会儿,想出了2个解决方案。 :-

  1. 存储已显示帖子的ID并查询WHERE ID NOT IN(id1,id2,...)。但是,这会花费你额外的内存。如果用户加载了 100 个页面并且 id 为 100000 秒,那么单个 GET 请求将无法处理它。至少不是在所有浏览器中。可以使用 POST 请求。

  2. 更改来自COL1 的帖子的显示方式。我不知道这对你来说是不是一个好方法。但是,它可以节省您的带宽并使您的代码更干净。这也可能是一个更好的方法。我建议这样做:-SELECT * from TABLE where COL1 IS NOT NULL AND COL2 IS NULL AND Id>.. ORDER BY ID DESC LIMIT 10,10。这可能会突飞猛进地影响您显示帖子的方式。但是,正如您在 cmets 中所说,您检查帖子是否符合标准并将 COL1 从 NULL 更改为当前时间戳,我猜帖子越新,您想要显示的越多。这只是一个想法。

【讨论】:

  • 第一种方法我之前已经试过了。但没有发现它非常可行。但是,我想我可以试试你的第二种方法。谢谢+1
【解决方案3】:

我假设新帖子的 ID 会比当前最大 ID 更高,对吧?所以你不能只运行查询并获取当前的最大 ID。然后,当您查询第 2 页时,请执行相同的查询,但使用“ID max_id。希望有帮助吗?

【讨论】:

    【解决方案4】:

    怎么样?

    ORDER BY `COL1`,`ID`;
    

    这将始终按顺序排列 ID。这将让您使用:

    LIMIT 10,10
    

    为您的第二页。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-28
      • 2018-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多