【问题标题】:How can I find next available value in a table in the fastest way如何以最快的方式在表中找到下一个可用值
【发布时间】:2022-11-23 02:36:05
【问题描述】:

我有一个包含索引的 varchar 列的表。此列中的值由一个前缀和一个递增的数字值组成。值没有必要按顺序排列。

ABC00010
ABC00011
ABC00015
ABC00012
ABC00017
ABC00016
and so on...

序列中可能存在缺失值。如何找到可用于插入的最小数字?

我写了这个并且它有效。但是当数字以千为单位时,需要几秒钟的时间。

Declare @C int = 1;
While Exists(Select 1 From MyTable Where Col='ABC'+Format(@C,'00000')) Set @C=@C+1;
Select 'Next Number: ABC'+Format(@C,'00000');

有没有更快的方法?

【问题讨论】:

  • 在提问时,您需要提供 minimal reproducible example: (1) DDL 和示例数据填充,即 CREATE table(s) 加上 INSERT T-SQL 语句。 (2) 您需要做什么,即逻辑和您的代码尝试在 T-SQL 中实现它。 (3) 期望的输出,基于上面 #1 中的示例数据。 (4) 您的 SQL Server 版本 (SELECT @@version;)。
  • 我在哪里创建这个?
  • 一种选择:dbfiddle.uk/-SXv3GHO
  • 有没有更快的方法?是的绝对 - 修复你的设计 - 如果你的表至少是 1NF 你就不需要乱搞分裂字符串或循环;一个专栏应该总是包含单个原子值。
  • 在 SQL Server 管理工作室 (SSMS) 中

标签: sql sql-server


【解决方案1】:

始终考虑基于集合的操作。 While 循环不是基于集合的。在这里,我创建了一个序列号从 0 到 99999 的 CTE。然后我将序列 CTE 与“MyTable”匹配,对列表进行排序,然后从 RIGHT JOIN 中选择一个 TOP 1

DECLARE @myTable TABLE (
    Col nvarchar(8)
);

INSERT INTO @myTable
VALUES ('ABC00001'), ('ABC00002'), ('ABC00005'), ('ABC00003')
;

WITH x AS (SELECT n FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) v(n))
, y as (
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as number
    FROM x ones, x tens, x hundreds, x thousands, x tThousands
)
, yMod as (
    SELECT y.number
        , 'ABC' + RIGHT('00000' + CAST(y.number as nvarchar), 5) as Col
    FROM y 
)
SELECT TOP 1
    ym.Col
FROM @myTable as mt
    RIGHT OUTER JOIN yMod as ym
        ON ym.Col = mt.Col
WHERE mt.Col IS NULL
ORDER BY ym.number

【讨论】:

  • 这很有趣。我试图想出一种基于集合的方法,但没有想到。我的实际用例有点复杂。但是让我看看我是否可以使用这种方法。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-14
  • 2016-03-07
  • 2019-09-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多