【问题标题】:How to make sure results from my query are continuous如何确保我的查询结果是连续的
【发布时间】:2019-10-23 17:14:40
【问题描述】:

我想查询一个有帐号的表,但是我需要从任意数字开始的 60000 的连续范围,只要它是连续的就没有关系。

我什么都想不出来,我只有一个基本的查询之间,但这甚至不好,因为我不想或不需要指定开始,只需要顺序范围。

Select *
From tableA
where account number between acctNum1 and acctNum2;

60000 个帐号的连续范围。

因此,如果有从 1 到 100 万的帐号,并且帐号中有随机间隙,我想看看我是否可以获得 60000 的数量但顺序。

【问题讨论】:

  • 你是说如果表中没有记录,你还是要返回一个帐号?我假设此表中还有其他列,在这种情况下它们应该是什么样的?
  • 您需要提供样本数据和想要的结果。为什么帐号不是连续的? (大概这就是您所说的“连续”的意思,因为帐号本质上是离散的。)
  • 帐号表,包含状态、所有者、日期等各种信息,当然也有帐号。现在,第一个帐号是 1,然后是 2,然后是 3,当它们生成时,它们是连续的,所以想象一下生成了一个表,其中帐号为 1 到 1,000,000。人们可以从这张表中分配,因此在 1 到 100 万之间可能会有任何缺失。所以 1201 可用,1202 可用,但 1203 不可用,因此 1201 和 1204 之间没有连续范围。只要有 60,000 的连续计数,我需要获取任何起始帐户编号和任何结束。
  • 您的问题被称为“差距和孤岛”,请阅读以下内容:red-gate.com/simple-talk/sql/t-sql-programming/… 并编辑您的问题,添加有关您的问题的更多详细信息,添加示例数据以显示您认为的问题以及您希望如何解决已解决。
  • 我无法提供数据,因为这是敏感数据,但我不确定如何使其更清晰。帐户表有很多列,除了帐号之外,这些列都无关紧要。这又是我理想的查询,但用的是文字。 “从帐号顺序和计数为60000的帐户表中选择”我将阅读您发布的文章。谢谢。

标签: sql


【解决方案1】:

可能是这样的:

以下返回包含 60,000 条连续记录的所有可能范围的列表。

它返回 3 列,分别是 StartAcct#、RN 和 EndAcct#。开始和结束定义了您可以使用的范围。

WITH CTE2 as (SELECT *, row_number() over (order by accountNumber) RN FROM SrcTable)
   , CTE3 as (SELECT AccountNumber as StartAcct#
                   , RN, LEAD(AccountNumber,60000-1) over(order by rn) as EndAcct#
              FROM CTE2 A)

SELECT * 
FROM CTE3
WHERE EndAcct#-StartAcct# = 60000-1

例如可能返回:(如果您正在寻找 20 的差距)...

+----+------------+----+----------+
|    | StartAcct# | RN | EndAcct# |
+----+------------+----+----------+
|  1 |         26 | 24 |       46 |
|  2 |         27 | 25 |       47 |
|  3 |         28 | 26 |       48 |
+----+------------+----+----------+
  • 将 SrcTable 调整为带有 accountNUMber 的表
  • 假设 AccountNumber 实际上是数字,您表示从 1 开始,然后从那里依次增加 1...
  • 假设您有可用的领先窗口函数/分析。

不太确定性能...因为实现 1,000,000 条记录的 cte 并为每个记录分配行号可能不是世界上最有效的事情...

Rextester Example 使用 100 条间隔记录返回所有间隔为 20 的记录,将 20 调整为 60,000 非常简单,而 20 只是概念证明。

现在我们有了开始和结束范围,我们可以得到有问题的 60,000 条记录。只需查询 accountNumber 位于 start 和 end 之间的基表...通过交叉连接到 CTE3 并将其限制为仅 1 条记录...

注意事项: Does SQL Server TOP stop processing once it finds enough rows? 似乎表明,如果您只是在第一次出现之后,Top 可能会提前退出......但我觉得这很难相信,因为必须应用订单......

因此必须进行测试以了解 top 或 limit 是否有利于查询。

其他尝试回答请随意利用创建的示例!

【讨论】:

  • 非常聪明的解决方案,如果我说我该死的自我:)
  • 只是利用 Lead() 的偏移能力。
  • 糟糕,我给了 60001... 需要从 60000 中减去一个,但这个概念仍然是合理的:P
【解决方案2】:

在我能够尝试上述答案之前,我发现了这个,它对我很有用。谢谢大家!

Find ranges from a series of numbers in SQL/Oracle

【讨论】:

    【解决方案3】:

    COUNT OVER 与范围窗口子句一起使用,以查看在 account_number - 59999 及其本身的范围内有多少行。选择第一个完整计数为 60000 的数字并从表中相应地选择。

    select *
    from mytable
    where 
    (
      select min(account_number)
      from
      (
        select
          account_number,
          count(*) over (order by account_number range between 59999 preceding and current row) as cnt
        from mytable
      ) viewed
      where cnt = 60000
    ) between account_number and account_number + 59999
    order by account_number;
    

    【讨论】:

    • 我试过这个,它只是运行和运行,我在大约 8 分钟后杀死了它,所以不确定是有错误还是需要更多时间。
    • 嗯,根据您的硬件,这样的查询可以运行很长时间。首先,必须对所有行进行排序,这可能很耗时——尤其是在内存不足的情况下。然后 DBMS 必须为每一行循环返回,直到达到 account_number - 59999。这也是很多工作。我确信 xQberts 的想法是简单地向前或向后准确地向前或向后 59999 行并检查该特定行是否包含所需的值必须更快。
    • awe shucks :P 我认为如果 accountNumber 上有索引,我的操作就可以了。除了必须为所有帐号生成一个行号之外,我看不出它在这种情况下太慢了......我想知道索引是否已经这样做了......呸我懒得检查;P
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-09
    • 1970-01-01
    • 2017-02-17
    • 1970-01-01
    • 2013-08-14
    相关资源
    最近更新 更多