【问题标题】:DIviding the SQL result into two halves将 SQL 结果分成两半
【发布时间】:2020-11-06 10:34:19
【问题描述】:

SQL 查询是:

Select ProductName from Products;

上述查询返回 5000 行。

如何将 5000 行的结果分成两个结果集,每个 2500 行,即一个从 1 到 2500 的结果集,另一个从 2501 到 5000 的结果集?

注意:

  1. 这里 ProductName 是主键。表中没有 ProductID 列。
  2. 可以在后端或前端完成。

【问题讨论】:

  • 使用您使用的 RDBMS 添加标签
  • 阅读您的 SQL 变体的文档。 LIMIT、OFFSET ... FETCH 等
  • @o.Jones 会有帮助吗?
  • 认真考虑处理应用代码中数据显示的问题

标签: mysql sql data-partitioning


【解决方案1】:

适用于 mySQL 的方法(基于此答案 https://stackoverflow.com/a/4741301/14015737):

上半部

  SELECT *
    FROM (
             SELECT test.*, @counter := @counter +1 counter
               FROM (select @counter:=0) initvar, test
           ORDER BY num
         ) X
   WHERE counter <= round(50/100 * @counter);
ORDER BY num;

下半部分

颠倒排序并去除舍入

  SELECT *
    FROM (
             SELECT test.*, @counter := @counter +1 counter
               FROM (select @counter:=0) initvar, test
           ORDER BY num DESC
         ) X
   WHERE counter <= (50/100 * @counter);
ORDER BY num;

本例中,如果记录数奇数,则将中间记录添加到上半部分。如果您希望反过来,请将round() 移至另一条语句。如果您根本不想要它,请删除 round()。

Dbfiddle 示例:https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=fb70eae0f7f1434a24099b5bb19f0878

【讨论】:

    【解决方案2】:

    如果您知道想要的数字,只需使用limit:

    select ProductName
    from Products
    order by id
    

    然后:

    limit 2500
    limit 2500 offset 2499
    

    如果你只是想把结果分成两半,那么你可以使用:

    select t.*
    from (select t.*,
                 ntile(2) over (order by <primary key>) as tile
          from t
         ) t
    where tile = 1;  -- or 2 for the other half
    

    【讨论】:

      【解决方案3】:

      如果您可以按顺序获取行,最简单且可能最快的方法是使用表的主键。

      运行

      select productname, id from products order by id;
      

      并获取 2500 行。然后使用最后一个 ID,比如 ID 3456,运行

      select productname, id from products where id > 3456 order by id;
      

      并再次获取 2500 行。等等。

      更新:看到我对此投了反对票,我会更好地解释:-)

      查询现在返回 5000 行,而 OP 不想要那么多行,所以他们想把它切成两半。但是该查询明年可能会返回 10000 行。 OP 会突然可以一次获得 5000 行吗?这似乎不太可能。更有可能存在不应超过的行数。这就是为什么我把数量切成2500片。

      另一种对所有行进行编号并返回前 n 行的方法有一个严重的缺点:必须再次读取所有行。即使决定将结果分成 100 个块,每次都必须读取、排序、编号、提取所有行。从表中读取所有行并对所有这些行进行排序对于 DBMS 来说是很多工作。

      【讨论】:

      • 我不知道为什么这会被否决。这似乎是一种合理的方法,尽管如果获取 2500 行,则 1234 的示例没有多大意义,因为数字主键通常不是负数。
      • @Gordon Linoff:谢谢。是的,ID 1234 没有意义。我已经更正了。
      猜你喜欢
      • 2013-05-25
      • 2013-12-06
      • 2012-05-26
      • 2023-02-16
      • 1970-01-01
      • 1970-01-01
      • 2017-07-31
      • 2015-12-02
      • 2020-07-20
      相关资源
      最近更新 更多