Select 范围内的最小数量
Select minimum number in a range
我有一个 table 数据类似。
ItemCode
1000
1002
1003
1020
1060
我正在尝试编写一个 SQL 语句来获取不在此 table 中的最小编号 (ItemCode) 并且它应该能够在上一个已在 table 中插入最小订单 ID,但也会跳过数据库中已有的数字。每次查询 运行.
我只想得到 1 个结果
所以,在上面的table的基础上,应该得到1001
作为第一个结果。一旦 ItemCode = 1001
被插入到 table 中,它应该得到的下一个结果应该是 1004
因为 1000
到 1003
已经存在于 table.
根据我在网上看到的所有内容,我想,我必须使用 While 循环来执行此操作。这是我仍在处理的代码。
DECLARE @Count int
SET @Count= 0
WHILE Exists (Select ItemCode
from OITM
where itemCode like '10%'
AND convert(int,ItemCode) >= '1000'
and convert(int,ItemCode) <= '1060')
Begin
SET @COUNT = @COUNT + 1
select MIN(ItemCode) + @Count
from OITM
where itemCode like '10%'
AND convert(int,ItemCode) >= '1000'
and convert(int,ItemCode) <= '1060'
END
我觉得必须有一种更简单的方法来完成此任务。有没有办法让我说...
select table X
中不存在的 1000 到 1060 之间的最小数字
编辑:创建一个新的 table 不是我的选择
最终编辑:谢谢大家!我知道了。这是我的最终查询 returns 正是我想要的。我知道我无缘无故地把它弄得太复杂了!
With T0 as ( select convert(int,ItemCode) + row_number() over (order by convert(int,ItemCode)) as ItemCode
from OITM
where itemCode like '10%'
AND convert(int,ItemCode) >= '1000'
And convert(int,ItemCode) <= '1060')
Select MIN(convert(varchar,ItemCode)) as ItemCode
from T0
where convert(int,ItemCode) Not in (Select convert(int,ItemCode)
from OITM
where itemCode like '10%'
AND convert(int,ItemCode) >= '1000'
and convert(int,ItemCode) <= '1060');
您可以使用 Tally Table 来做到这一点。查看 Jeff Moden 的 article 以供参考。
基本上,您想要生成从 @start
到 @end
的数字。这就是 Tally Table 的用武之地。它将用于数字生成。有了数字后,您只需检查 table.
中不存在的最小值
DECLARE @start INT = 1000
DECLARE @end INT = 1060
;WITH E1(N) AS(
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
)
,E2(N) AS(SELECT 1 FROM E1 a, E1 b)
,E4(N) AS(SELECT 1 FROM E2 a, E2 b)
,Tally(N) AS(
SELECT TOP(@end - @start + 1) ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) - 1 FROM E4
)
SELECT
MIN(@start + t.N)
FROM Tally t
WHERE
@start + t.N <= @end
AND NOT EXISTS(
SELECT 1
FROM OITM
WHERE CAST(ItemCode AS INT) = @start + t.N
)
这是另一个使用 sys.columns
生成 Tally Table 的查询:
;WITH Tally(N) AS(
SELECT TOP(@end - @start + 1) ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) - 1
FROM sys.columns a
--CROSS JOIN sys.columns b
)
SELECT
MIN(@start + t.N)
FROM Tally t
WHERE
@start + t.N <= @end
AND NOT EXISTS(
SELECT 1
FROM OITM
WHERE CAST(ItemCode AS INT) = @start + t.N
)
您可以使用 row_number()
为每一行生成顺序值,然后查找 row_number()
与存储在 table 中的值不匹配的第一行。我的 SQL 服务器安装目前不工作,SQL Fiddle 似乎也出现故障,所以我写了这篇文章但无法测试它,但像这样的东西应该可以工作:
declare @lowerBound int = 1000;
declare @upperBound int = 1060;
declare @x table ([id] int);
insert @x values (1000), (1002), (1003), (1020), (1060);
with [SequenceCTE] as
(
select
[id],
[seq] = (@lowerBound - 1) + row_number() over (order by [id])
from
@x
)
select top 1
[seq]
from
[SequenceCTE]
where
[seq] != [id] and
[seq] <= @upperBound;
编辑: Here 是演示此方法的 SQL Fiddle。我不知道为什么该网站以前不适合我。由于某种原因,它似乎不喜欢我的 declare
语句,所以我改为硬编码边界,但希望它仍然能理解这个想法。
这应该可以做到。在这里,您为行生成序列号,然后将每一行与下一行进行比较(通过连接条件完成),并仅过滤差异不为 1 的那些行,按顺序排序,最后选择最上面的行。
;with c as(select id, row_number() over(order by id) rn)
select top 1 c1.id + 1 as NewID
from c as c1
join c as c2 on c1.rn + 1 = c2.rn
where c2.id - c1.id <> 1
order by c1.rn
我有一个 table 数据类似。
ItemCode
1000
1002
1003
1020
1060
我正在尝试编写一个 SQL 语句来获取不在此 table 中的最小编号 (ItemCode) 并且它应该能够在上一个已在 table 中插入最小订单 ID,但也会跳过数据库中已有的数字。每次查询 运行.
我只想得到 1 个结果所以,在上面的table的基础上,应该得到1001
作为第一个结果。一旦 ItemCode = 1001
被插入到 table 中,它应该得到的下一个结果应该是 1004
因为 1000
到 1003
已经存在于 table.
根据我在网上看到的所有内容,我想,我必须使用 While 循环来执行此操作。这是我仍在处理的代码。
DECLARE @Count int
SET @Count= 0
WHILE Exists (Select ItemCode
from OITM
where itemCode like '10%'
AND convert(int,ItemCode) >= '1000'
and convert(int,ItemCode) <= '1060')
Begin
SET @COUNT = @COUNT + 1
select MIN(ItemCode) + @Count
from OITM
where itemCode like '10%'
AND convert(int,ItemCode) >= '1000'
and convert(int,ItemCode) <= '1060'
END
我觉得必须有一种更简单的方法来完成此任务。有没有办法让我说...
select table X
中不存在的 1000 到 1060 之间的最小数字编辑:创建一个新的 table 不是我的选择
最终编辑:谢谢大家!我知道了。这是我的最终查询 returns 正是我想要的。我知道我无缘无故地把它弄得太复杂了!
With T0 as ( select convert(int,ItemCode) + row_number() over (order by convert(int,ItemCode)) as ItemCode
from OITM
where itemCode like '10%'
AND convert(int,ItemCode) >= '1000'
And convert(int,ItemCode) <= '1060')
Select MIN(convert(varchar,ItemCode)) as ItemCode
from T0
where convert(int,ItemCode) Not in (Select convert(int,ItemCode)
from OITM
where itemCode like '10%'
AND convert(int,ItemCode) >= '1000'
and convert(int,ItemCode) <= '1060');
您可以使用 Tally Table 来做到这一点。查看 Jeff Moden 的 article 以供参考。
基本上,您想要生成从 @start
到 @end
的数字。这就是 Tally Table 的用武之地。它将用于数字生成。有了数字后,您只需检查 table.
DECLARE @start INT = 1000
DECLARE @end INT = 1060
;WITH E1(N) AS(
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
)
,E2(N) AS(SELECT 1 FROM E1 a, E1 b)
,E4(N) AS(SELECT 1 FROM E2 a, E2 b)
,Tally(N) AS(
SELECT TOP(@end - @start + 1) ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) - 1 FROM E4
)
SELECT
MIN(@start + t.N)
FROM Tally t
WHERE
@start + t.N <= @end
AND NOT EXISTS(
SELECT 1
FROM OITM
WHERE CAST(ItemCode AS INT) = @start + t.N
)
这是另一个使用 sys.columns
生成 Tally Table 的查询:
;WITH Tally(N) AS(
SELECT TOP(@end - @start + 1) ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) - 1
FROM sys.columns a
--CROSS JOIN sys.columns b
)
SELECT
MIN(@start + t.N)
FROM Tally t
WHERE
@start + t.N <= @end
AND NOT EXISTS(
SELECT 1
FROM OITM
WHERE CAST(ItemCode AS INT) = @start + t.N
)
您可以使用 row_number()
为每一行生成顺序值,然后查找 row_number()
与存储在 table 中的值不匹配的第一行。我的 SQL 服务器安装目前不工作,SQL Fiddle 似乎也出现故障,所以我写了这篇文章但无法测试它,但像这样的东西应该可以工作:
declare @lowerBound int = 1000;
declare @upperBound int = 1060;
declare @x table ([id] int);
insert @x values (1000), (1002), (1003), (1020), (1060);
with [SequenceCTE] as
(
select
[id],
[seq] = (@lowerBound - 1) + row_number() over (order by [id])
from
@x
)
select top 1
[seq]
from
[SequenceCTE]
where
[seq] != [id] and
[seq] <= @upperBound;
编辑: Here 是演示此方法的 SQL Fiddle。我不知道为什么该网站以前不适合我。由于某种原因,它似乎不喜欢我的 declare
语句,所以我改为硬编码边界,但希望它仍然能理解这个想法。
这应该可以做到。在这里,您为行生成序列号,然后将每一行与下一行进行比较(通过连接条件完成),并仅过滤差异不为 1 的那些行,按顺序排序,最后选择最上面的行。
;with c as(select id, row_number() over(order by id) rn)
select top 1 c1.id + 1 as NewID
from c as c1
join c as c2 on c1.rn + 1 = c2.rn
where c2.id - c1.id <> 1
order by c1.rn