두 숫자 사이의 숫자 범위를 생성하는 방법은 무엇입니까?
으로 두 . , '나에게 줄 수 . 예를 들어 다음과 같습니다.1000
★★★★★★★★★★★★★★★★★」1050
.
sql 쿼리를 사용하여 이 두 숫자 사이의 숫자를 다른 행으로 생성하려면 어떻게 해야 합니까?나는 이것을 원한다:
1000
1001
1002
1003
.
.
1050
은 '인 값으로 선택합니다.VALUES
키워드를 지정합니다. '아예'를 사용합니다.JOIN
s는 수많은 조합을 생성합니다(수십만 행 이상을 생성하도록 확장할 수 있습니다).
짧고 빠른 버전(읽기 쉽지 않음):
WITH x AS (SELECT n FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) v(n))
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM x ones, x tens, x hundreds, x thousands
ORDER BY 1
상세 버전:
SELECT ones.n + 10*tens.n + 100*hundreds.n + 1000*thousands.n
FROM (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) ones(n),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) tens(n),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) hundreds(n),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) thousands(n)
ORDER BY 1
모두 쉽게 할 수 .WHERE
사용자가 지정한 범위로 번호 출력을 제한합니다.재사용할 경우 테이블 값 함수를 정의할 수 있습니다.
대체 솔루션은 재귀 CTE입니다.
DECLARE @startnum INT=1000
DECLARE @endnum INT=1050
;
WITH gen AS (
SELECT @startnum AS num
UNION ALL
SELECT num+1 FROM gen WHERE num+1<=@endnum
)
SELECT * FROM gen
option (maxrecursion 10000)
SELECT DISTINCT n = number
FROM master..[spt_values]
WHERE number BETWEEN @start AND @end
이 테이블의 최대값은 2048입니다.숫자에 공백이 생기기 때문입니다.
다음은 SQL-Server 2005부터의 시스템 뷰를 사용한 조금 더 나은 접근법입니다.
;WITH Nums AS
(
SELECT n = ROW_NUMBER() OVER (ORDER BY [object_id])
FROM sys.all_objects
)
SELECT n FROM Nums
WHERE n BETWEEN @start AND @end
ORDER BY n;
또는 커스텀 번호표를 사용합니다.Aaron Bertrand씨, 기사 전체를 읽어보시길 권합니다.루프 없는 세트 또는 시퀀스 생성
제가 사용한 최선의 옵션은 다음과 같습니다.
DECLARE @min bigint, @max bigint
SELECT @Min=919859000000 ,@Max=919859999999
SELECT TOP (@Max-@Min+1) @Min-1+row_number() over(order by t1.number) as N
FROM master..spt_values t1
CROSS JOIN master..spt_values t2
나는 이것을 사용하여 수백만 개의 레코드를 생성했고 그것은 완벽하게 작동한다.
저는 바로 이 문제를 해결하기 위해 최근에 이 인라인 테이블 값 함수를 작성했습니다.메모리나 스토리지 이외의 범위에는 제한이 없습니다.테이블에는 액세스 할 수 없기 때문에 일반적으로 디스크를 읽거나 쓸 필요가 없습니다.각 반복마다 조인 값이 기하급수적으로 추가되므로 매우 큰 범위에서도 매우 빠릅니다.내 서버에서 5초 만에 천만 개의 레코드가 생성됩니다.그것은 또한 음의 값에도 작용합니다.
CREATE FUNCTION [dbo].[fn_ConsecutiveNumbers]
(
@start int,
@end int
) RETURNS TABLE
RETURN
select
x268435456.X
| x16777216.X
| x1048576.X
| x65536.X
| x4096.X
| x256.X
| x16.X
| x1.X
+ @start
X
from
(VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15)) as x1(X)
join
(VALUES (0),(16),(32),(48),(64),(80),(96),(112),(128),(144),(160),(176),(192),(208),(224),(240)) as x16(X)
on x1.X <= @end-@start and x16.X <= @end-@start
join
(VALUES (0),(256),(512),(768),(1024),(1280),(1536),(1792),(2048),(2304),(2560),(2816),(3072),(3328),(3584),(3840)) as x256(X)
on x256.X <= @end-@start
join
(VALUES (0),(4096),(8192),(12288),(16384),(20480),(24576),(28672),(32768),(36864),(40960),(45056),(49152),(53248),(57344),(61440)) as x4096(X)
on x4096.X <= @end-@start
join
(VALUES (0),(65536),(131072),(196608),(262144),(327680),(393216),(458752),(524288),(589824),(655360),(720896),(786432),(851968),(917504),(983040)) as x65536(X)
on x65536.X <= @end-@start
join
(VALUES (0),(1048576),(2097152),(3145728),(4194304),(5242880),(6291456),(7340032),(8388608),(9437184),(10485760),(11534336),(12582912),(13631488),(14680064),(15728640)) as x1048576(X)
on x1048576.X <= @end-@start
join
(VALUES (0),(16777216),(33554432),(50331648),(67108864),(83886080),(100663296),(117440512),(134217728),(150994944),(167772160),(184549376),(201326592),(218103808),(234881024),(251658240)) as x16777216(X)
on x16777216.X <= @end-@start
join
(VALUES (0),(268435456),(536870912),(805306368),(1073741824),(1342177280),(1610612736),(1879048192)) as x268435456(X)
on x268435456.X <= @end-@start
WHERE @end >=
x268435456.X
| isnull(x16777216.X, 0)
| isnull(x1048576.X, 0)
| isnull(x65536.X, 0)
| isnull(x4096.X, 0)
| isnull(x256.X, 0)
| isnull(x16.X, 0)
| isnull(x1.X, 0)
+ @start
GO
SELECT X FROM fn_ConsecutiveNumbers(5, 500);
날짜 및 시간 범위에서도 편리합니다.
SELECT DATEADD(day,X, 0) DayX
FROM fn_ConsecutiveNumbers(datediff(day,0,'5/8/2015'), datediff(day,0,'5/31/2015'))
SELECT DATEADD(hour,X, 0) HourX
FROM fn_ConsecutiveNumbers(datediff(hour,0,'5/8/2015'), datediff(hour,0,'5/8/2015 12:00 PM'));
테이블 내의 값에 따라 레코드를 분할하려면 크로스 적용 결합을 사용할 수 있습니다.예를 들어 테이블 내의 시간 범위에서 매분 레코드를 작성하려면 다음과 같은 작업을 수행할 수 있습니다.
select TimeRanges.StartTime,
TimeRanges.EndTime,
DATEADD(minute,X, 0) MinuteX
FROM TimeRanges
cross apply fn_ConsecutiveNumbers(datediff(hour,0,TimeRanges.StartTime),
datediff(hour,0,TimeRanges.EndTime)) ConsecutiveNumbers
나한텐 효과가 있어!
select top 50 ROW_NUMBER() over(order by a.name) + 1000 as Rcount
from sys.all_objects a
재귀적인 ctes를 사용하여 실행하지만 이것이 최선의 방법인지 잘 모르겠습니다.
declare @initial as int = 1000;
declare @final as int =1050;
with cte_n as (
select @initial as contador
union all
select contador+1 from cte_n
where contador <@final
) select * from cte_n option (maxrecursion 0)
살루도
declare @start int = 1000
declare @end int =1050
;with numcte
AS
(
SELECT @start [SEQUENCE]
UNION all
SELECT [SEQUENCE] + 1 FROM numcte WHERE [SEQUENCE] < @end
)
SELECT * FROM numcte
서버에 CLR 어셈블리를 설치하는 데 문제가 없다면 테이블 값 함수를 에 쓰는 것이 좋습니다.NET. 이렇게 하면 간단한 구문을 사용할 수 있으므로 다른 쿼리와 쉽게 결합할 수 있으며, 결과가 스트리밍되기 때문에 보너스로 메모리가 낭비하지 않습니다.
다음 클래스를 포함하는 프로젝트를 만듭니다.
using System;
using System.Collections;
using System.Data;
using System.Data.Sql;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
namespace YourNamespace
{
public sealed class SequenceGenerator
{
[SqlFunction(FillRowMethodName = "FillRow")]
public static IEnumerable Generate(SqlInt32 start, SqlInt32 end)
{
int _start = start.Value;
int _end = end.Value;
for (int i = _start; i <= _end; i++)
yield return i;
}
public static void FillRow(Object obj, out int i)
{
i = (int)obj;
}
private SequenceGenerator() { }
}
}
어셈블리를 서버상의 어딘가에 배치하고 다음을 실행합니다.
USE db;
CREATE ASSEMBLY SqlUtil FROM 'c:\path\to\assembly.dll'
WITH permission_set=Safe;
CREATE FUNCTION [Seq](@start int, @end int)
RETURNS TABLE(i int)
AS EXTERNAL NAME [SqlUtil].[YourNamespace.SequenceGenerator].[Generate];
이제 실행할 수 있습니다.
select * from dbo.seq(1, 1000000)
slartidan의 답변은 데카르트 곱에 대한 모든 참조를 제거하고 사용함으로써 성능 면에서 개선될 수 있습니다.ROW_NUMBER()
대신 (플랜 비교):
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS n FROM
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) x1(x),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) x2(x),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) x3(x),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) x4(x),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) x5(x)
ORDER BY n
CTE 안에 랩하고 where 구를 추가하여 원하는 번호를 선택합니다.
DECLARE @n1 AS INT = 100;
DECLARE @n2 AS INT = 40099;
WITH numbers AS (
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS n FROM
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) x1(x),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) x2(x),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) x3(x),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) x4(x),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) x5(x)
)
SELECT numbers.n
FROM numbers
WHERE n BETWEEN @n1 and @n2
ORDER BY n
Brian Pressler 솔루션을 수정한 것은 새로운 것이 아닙니다.외관상 보기 편하도록 수정한 것입니다(미래의 저라도).
alter function [dbo].[fn_GenerateNumbers]
(
@start int,
@end int
) returns table
return
with
b0 as (select n from (values (0),(0x00000001),(0x00000002),(0x00000003),(0x00000004),(0x00000005),(0x00000006),(0x00000007),(0x00000008),(0x00000009),(0x0000000A),(0x0000000B),(0x0000000C),(0x0000000D),(0x0000000E),(0x0000000F)) as b0(n)),
b1 as (select n from (values (0),(0x00000010),(0x00000020),(0x00000030),(0x00000040),(0x00000050),(0x00000060),(0x00000070),(0x00000080),(0x00000090),(0x000000A0),(0x000000B0),(0x000000C0),(0x000000D0),(0x000000E0),(0x000000F0)) as b1(n)),
b2 as (select n from (values (0),(0x00000100),(0x00000200),(0x00000300),(0x00000400),(0x00000500),(0x00000600),(0x00000700),(0x00000800),(0x00000900),(0x00000A00),(0x00000B00),(0x00000C00),(0x00000D00),(0x00000E00),(0x00000F00)) as b2(n)),
b3 as (select n from (values (0),(0x00001000),(0x00002000),(0x00003000),(0x00004000),(0x00005000),(0x00006000),(0x00007000),(0x00008000),(0x00009000),(0x0000A000),(0x0000B000),(0x0000C000),(0x0000D000),(0x0000E000),(0x0000F000)) as b3(n)),
b4 as (select n from (values (0),(0x00010000),(0x00020000),(0x00030000),(0x00040000),(0x00050000),(0x00060000),(0x00070000),(0x00080000),(0x00090000),(0x000A0000),(0x000B0000),(0x000C0000),(0x000D0000),(0x000E0000),(0x000F0000)) as b4(n)),
b5 as (select n from (values (0),(0x00100000),(0x00200000),(0x00300000),(0x00400000),(0x00500000),(0x00600000),(0x00700000),(0x00800000),(0x00900000),(0x00A00000),(0x00B00000),(0x00C00000),(0x00D00000),(0x00E00000),(0x00F00000)) as b5(n)),
b6 as (select n from (values (0),(0x01000000),(0x02000000),(0x03000000),(0x04000000),(0x05000000),(0x06000000),(0x07000000),(0x08000000),(0x09000000),(0x0A000000),(0x0B000000),(0x0C000000),(0x0D000000),(0x0E000000),(0x0F000000)) as b6(n)),
b7 as (select n from (values (0),(0x10000000),(0x20000000),(0x30000000),(0x40000000),(0x50000000),(0x60000000),(0x70000000)) as b7(n))
select s.n
from (
select
b7.n
| b6.n
| b5.n
| b4.n
| b3.n
| b2.n
| b1.n
| b0.n
+ @start
n
from b0
join b1 on b0.n <= @end-@start and b1.n <= @end-@start
join b2 on b2.n <= @end-@start
join b3 on b3.n <= @end-@start
join b4 on b4.n <= @end-@start
join b5 on b5.n <= @end-@start
join b6 on b6.n <= @end-@start
join b7 on b7.n <= @end-@start
) s
where @end >= s.n
GO
SQL 서버 버전이 2022보다 높거나 GENERATE_SERES 함수를 지원하는 경우 GENERATE_SERES 함수를 사용하여 선언할 수 있습니다.START
★★★★★★★★★★★★★★★★★」STOP
파라미터를 지정합니다.
GENERATE_SERIES
STEP과 값의 합니다.
declare @start int = 1000
declare @stop int = 1050
declare @step int = 2
SELECT [Value]
FROM GENERATE_SERIES(@start, @stop, @step)
2년 후, 같은 문제가 생겼다는 것을 알게 되었습니다.해결 방법은 다음과 같습니다. (매개변수 포함 편집)
DECLARE @Start INT, @End INT
SET @Start = 1000
SET @End = 1050
SELECT TOP (@End - @Start+1) ROW_NUMBER() OVER (ORDER BY S.[object_id])+(@Start - 1) [Numbers]
FROM sys.all_objects S WITH (NOLOCK)
제가 4년 늦었다는 것을 알지만, 이 문제에 대한 또 다른 대안을 우연히 발견했습니다.속도 문제는 사전 필터링뿐만 아니라 정렬을 방해하는 것입니다.결합의 결과로 데카르트 곱이 실제로 카운트업되는 방식으로 결합 순서를 강제로 실행할 수 있습니다.슬라티단의 답을 출발점으로 삼는다:
WITH x AS (SELECT n FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) v(n))
SELECT ones.n + 10*tens.n + 100*hundreds.n + 1000*thousands.n
FROM x ones, x tens, x hundreds, x thousands
ORDER BY 1
원하는 범위를 알고 있으면 @Upper 및 Lower를 통해 지정할 수 있습니다.조인힌트 REMOTE와 TOP를 조합함으로써 낭비 없이 원하는 값의 서브셋만 계산할 수 있습니다.
WITH x AS (SELECT n FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) v(n))
SELECT TOP (1+@Upper-@Lower) @Lower + ones.n + 10*tens.n + 100*hundreds.n + 1000*thousands.n
FROM x thousands
INNER REMOTE JOIN x hundreds on 1=1
INNER REMOTE JOIN x tens on 1=1
INNER REMOTE JOIN x ones on 1=1
join hint REMOTE는 옵티마이저가 먼저 join 오른쪽에서 비교하도록 강제합니다.각 조인 값을 REMOTE로 지정하면 조인 자체가 1씩 위쪽으로 올바르게 카운트됩니다.WHERE로 필터링하거나 ORDER BY로 정렬할 필요가 없습니다.
범위를 늘리려면 FROM 절에서 중요도가 가장 높은 순서대로 정렬되어 있는 한 계속해서 더 높은 크기의 조인(join)을 추가할 수 있습니다.
이는 SQL Server 2008 이상에 고유한 쿼리입니다.
다음은 최적의 호환 솔루션 몇 가지입니다.
USE master;
declare @min as int; set @min = 1000;
declare @max as int; set @max = 1050; --null returns all
-- Up to 256 - 2 048 rows depending on SQL Server version
select isnull(@min,0)+number.number as number
FROM dbo.spt_values AS number
WHERE number."type" = 'P' --integers
and ( @max is null --return all
or isnull(@min,0)+number.number <= @max --return up to max
)
order by number
;
-- Up to 65 536 - 4 194 303 rows depending on SQL Server version
select isnull(@min,0)+value1.number+(value2.number*numberCount.numbers) as number
FROM dbo.spt_values AS value1
cross join dbo.spt_values AS value2
cross join ( --get the number of numbers (depends on version)
select sum(1) as numbers
from dbo.spt_values
where spt_values."type" = 'P' --integers
) as numberCount
WHERE value1."type" = 'P' --integers
and value2."type" = 'P' --integers
and ( @max is null --return all
or isnull(@min,0)+value1.number+(value2.number*numberCount.numbers)
<= @max --return up to max
)
order by number
;
지수 크기의 재귀 CTE(디폴트 100 재귀의 경우에도 최대 2^100의 번호를 구축할 수 있습니다):
DECLARE @startnum INT=1000
DECLARE @endnum INT=1050
DECLARE @size INT=@endnum-@startnum+1
;
WITH numrange (num) AS (
SELECT 1 AS num
UNION ALL
SELECT num*2 FROM numrange WHERE num*2<=@size
UNION ALL
SELECT num*2+1 FROM numrange WHERE num*2+1<=@size
)
SELECT num+@startnum-1 FROM numrange order by num
SQL 2017 이상 업데이트:원하는 시퀀스가 8k 미만일 경우 다음과 같이 동작합니다.
Declare @start_num int = 1000
, @end_num int = 1050
Select [number] = @start_num + ROW_NUMBER() over (order by (Select null))
from string_split(replicate(' ',@end_num-@start_num-1),' ')
이것도 좋다
DECLARE @startNum INT = 1000;
DECLARE @endNum INT = 1050;
INSERT INTO dbo.Numbers
( Num
)
SELECT CASE WHEN MAX(Num) IS NULL THEN @startNum
ELSE MAX(Num) + 1
END AS Num
FROM dbo.Numbers
GO 51
쿼리를 실행할 때 가장 빠른 속도
DECLARE @num INT = 1000
WHILE(@num<1050)
begin
INSERT INTO [dbo].[Codes]
( Code
)
VALUES (@num)
SET @num = @num + 1
end
비슷한 방법으로 사진 파일 경로를 데이터베이스에 삽입해야 했습니다.아래 쿼리는 정상적으로 동작했습니다.
DECLARE @num INT = 8270058
WHILE(@num<8270284)
begin
INSERT INTO [dbo].[Galleries]
(ImagePath)
VALUES
('~/Content/Galeria/P'+CONVERT(varchar(10), @num)+'.JPG')
SET @num = @num + 1
end
암호는 다음과 같습니다.
DECLARE @num INT = 1000
WHILE(@num<1051)
begin
SELECT @num
SET @num = @num + 1
end
제가 생각해낸 것은 다음과 같습니다.
create or alter function dbo.fn_range(@start int, @end int) returns table
return
with u2(n) as (
select n
from (VALUES (0),(1),(2),(3)) v(n)
),
u8(n) as (
select
x0.n | x1.n * 4 | x2.n * 16 | x3.n * 64 as n
from u2 x0, u2 x1, u2 x2, u2 x3
)
select
@start + s.n as n
from (
select
x0.n | isnull(x1.n, 0) * 256 | isnull(x2.n, 0) * 65536 as n
from u8 x0
left join u8 x1 on @end-@start > 256
left join u8 x2 on @end-@start > 65536
) s
where s.n < @end - @start
최대 2^24 값을 생성합니다.결합 조건에서는 작은 값에서도 고속으로 유지됩니다.
이게 제가 하는 일입니다. 매우 빠르고 유연하며 많은 코드가 없습니다.
DECLARE @count int = 65536;
DECLARE @start int = 11;
DECLARE @xml xml = REPLICATE(CAST('<x/>' AS nvarchar(max)), @count);
; WITH GenerateNumbers(Num) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY @count) + @start - 1
FROM @xml.nodes('/x') X(T)
)
SELECT Num
FROM GenerateNumbers;
(ORDER BY @count)는 더미입니다.ROW_NUMBER()는 ORDER BY를 요구합니다.
편집: 원래 질문은 x에서 y까지의 범위를 구하는 것이었음을 깨달았습니다.스크립트를 다음과 같이 수정하여 범위를 얻을 수 있습니다.
DECLARE @start int = 5;
DECLARE @end int = 21;
DECLARE @xml xml = REPLICATE(CAST('<x/>' AS nvarchar(max)), @end - @start + 1);
; WITH GenerateNumbers(Num) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY @end) + @start - 1
FROM @xml.nodes('/x') X(T)
)
SELECT Num
FROM GenerateNumbers;
-- Generate Numeric Range
-- Source: http://www.sqlservercentral.com/scripts/Miscellaneous/30397/
CREATE TABLE #NumRange(
n int
)
DECLARE @MinNum int
DECLARE @MaxNum int
DECLARE @I int
SET NOCOUNT ON
SET @I = 0
WHILE @I <= 9 BEGIN
INSERT INTO #NumRange VALUES(@I)
SET @I = @I + 1
END
SET @MinNum = 1
SET @MaxNum = 1000000
SELECT num = a.n +
(b.n * 10) +
(c.n * 100) +
(d.n * 1000) +
(e.n * 10000)
FROM #NumRange a
CROSS JOIN #NumRange b
CROSS JOIN #NumRange c
CROSS JOIN #NumRange d
CROSS JOIN #NumRange e
WHERE a.n +
(b.n * 10) +
(c.n * 100) +
(d.n * 1000) +
(e.n * 10000) BETWEEN @MinNum AND @MaxNum
ORDER BY a.n +
(b.n * 10) +
(c.n * 100) +
(d.n * 1000) +
(e.n * 10000)
DROP TABLE #NumRange
이것은 일부 응용 프로그램테이블에 행이 있는 한 시퀀스에 대해서만 기능합니다.내가 1부터의 시퀀스를 원한다고 가정해봐.100, 어플리케이션테이블 dbo가 필요합니다.foo (숫자 또는 문자열 유형의 열)foo.bar:
select
top 100
row_number() over (order by dbo.foo.bar) as seq
from dbo.foo
dbo.foo.bar은 order by 절에 존재하지만 고유한 값이나 비표준 값을 가질 필요는 없습니다.
물론 SQL Server 2012에는 시퀀스 객체가 있기 때문에 그 제품에는 자연스러운 솔루션이 있습니다.
이 작업은 DEV 서버에서 36초 만에 완료되었습니다.Brian의 답변처럼 범위 필터링에 집중하는 것이 쿼리 내에서 중요합니다.BETWIN은 필요 없는 경우에도 하한 전에 모든 초기 레코드를 생성하려고 합니다.
declare @s bigint = 10000000
, @e bigint = 20000000
;WITH
Z AS (SELECT 0 z FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15)) T(n)),
Y AS (SELECT 0 z FROM Z a, Z b, Z c, Z d, Z e, Z f, Z g, Z h, Z i, Z j, Z k, Z l, Z m, Z n, Z o, Z p),
N AS (SELECT ROW_NUMBER() OVER (PARTITION BY 0 ORDER BY z) n FROM Y)
SELECT TOP (1+@e-@s) @s + n - 1 FROM N
ROW_NUMBER는 bigint이기 때문에 2^^64(^^16^^16)의 생성된 레코드는 사용할 수 없습니다.따라서 이 쿼리는 생성된 값에 대한 동일한 상한을 준수합니다.
여기에는 절차 코드와 테이블 값 함수가 사용됩니다.느리지만 쉽게 예측할 수 있습니다.
CREATE FUNCTION [dbo].[Sequence] (@start int, @end int)
RETURNS
@Result TABLE(ID int)
AS
begin
declare @i int;
set @i = @start;
while @i <= @end
begin
insert into @result values (@i);
set @i = @i+1;
end
return;
end
사용방법:
SELECT * FROM dbo.Sequence (3,7);
ID
3
4
5
6
7
테이블이므로 다른 데이터와 함께 사용할 수 있습니다.시간 값의 연속 시퀀스를 보장하기 위해 GROUP BY, Day 등에 대한 조인의 좌측으로 이 함수를 가장 자주 사용합니다.
SELECT DateAdd(hh,ID,'2018-06-20 00:00:00') as HoursInTheDay FROM dbo.Sequence (0,23) ;
HoursInTheDay
2018-06-20 00:00:00.000
2018-06-20 01:00:00.000
2018-06-20 02:00:00.000
2018-06-20 03:00:00.000
2018-06-20 04:00:00.000
(...)
퍼포먼스는 자극적이지 않지만(100만 행에 대해 16초) 다목적에는 충분합니다.
SELECT count(1) FROM [dbo].[Sequence] (
1000001
,2000000)
GO
Oracle 12c, 신속하지만 제한적:
select rownum+1000 from all_objects fetch first 50 rows only;
주의: all_objects 뷰의 행 개수로 제한됩니다.
제가 오랫동안 개발하여 사용해 온 솔루션(다른 사람의 공유된 작품에 따라)은 적어도 게시된 솔루션 중 하나와 약간 비슷합니다.테이블을 참조하지 않고 최대 1048576 값(2^20)의 정렬되지 않은 범위를 반환합니다.필요한 경우 음수를 포함할 수 있습니다.물론 필요한 경우 결과를 정렬할 수 있습니다.특히 더 작은 범위에서 매우 빠르게 작동합니다.
Select value from dbo.intRange(-500, 1500) order by value -- returns 2001 values
create function dbo.intRange
(
@Starting as int,
@Ending as int
)
returns table
as
return (
select value
from (
select @Starting +
( bit00.v | bit01.v | bit02.v | bit03.v
| bit04.v | bit05.v | bit06.v | bit07.v
| bit08.v | bit09.v | bit10.v | bit11.v
| bit12.v | bit13.v | bit14.v | bit15.v
| bit16.v | bit17.v | bit18.v | bit19.v
) as value
from (select 0 as v union ALL select 0x00001 as v) as bit00
cross join (select 0 as v union ALL select 0x00002 as v) as bit01
cross join (select 0 as v union ALL select 0x00004 as v) as bit02
cross join (select 0 as v union ALL select 0x00008 as v) as bit03
cross join (select 0 as v union ALL select 0x00010 as v) as bit04
cross join (select 0 as v union ALL select 0x00020 as v) as bit05
cross join (select 0 as v union ALL select 0x00040 as v) as bit06
cross join (select 0 as v union ALL select 0x00080 as v) as bit07
cross join (select 0 as v union ALL select 0x00100 as v) as bit08
cross join (select 0 as v union ALL select 0x00200 as v) as bit09
cross join (select 0 as v union ALL select 0x00400 as v) as bit10
cross join (select 0 as v union ALL select 0x00800 as v) as bit11
cross join (select 0 as v union ALL select 0x01000 as v) as bit12
cross join (select 0 as v union ALL select 0x02000 as v) as bit13
cross join (select 0 as v union ALL select 0x04000 as v) as bit14
cross join (select 0 as v union ALL select 0x08000 as v) as bit15
cross join (select 0 as v union ALL select 0x10000 as v) as bit16
cross join (select 0 as v union ALL select 0x20000 as v) as bit17
cross join (select 0 as v union ALL select 0x40000 as v) as bit18
cross join (select 0 as v union ALL select 0x80000 as v) as bit19
) intList
where @Ending - @Starting < 0x100000
and intList.value between @Starting and @Ending
)
;WITH u AS (
SELECT Unit FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) v(Unit)
),
d AS (
SELECT
(Thousands+Hundreds+Tens+Units) V
FROM
(SELECT Thousands = Unit * 1000 FROM u) Thousands
,(SELECT Hundreds = Unit * 100 FROM u) Hundreds
,(SELECT Tens = Unit * 10 FROM u) Tens
,(SELECT Units = Unit FROM u) Units
WHERE
(Thousands+Hundreds+Tens+Units) <= 10000
)
SELECT * FROM d ORDER BY v
저는 이 스레드를 읽고 아래 기능을 만들었습니다.심플하고 고속:
go
create function numbers(@begin int, @len int)
returns table as return
with d as (
select 1 v from (values(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) d(v)
)
select top (@len) @begin -1 + row_number() over(order by (select null)) v
from d d0
cross join d d1
cross join d d2
cross join d d3
cross join d d4
cross join d d5
cross join d d6
cross join d d7
go
select * from numbers(987654321,500000)
언급URL : https://stackoverflow.com/questions/21425546/how-to-generate-a-range-of-numbers-between-two-numbers
'programing' 카테고리의 다른 글
SQL Server 값 목록에서 선택하는 방법 (0) | 2023.04.07 |
---|---|
SQL Server에서의 내부 참여와 왼쪽 참여의 퍼포먼스 (0) | 2023.04.07 |
null도 허용하는 고유한 제약조건을 작성하려면 어떻게 해야 합니까? (0) | 2023.04.07 |
MemoryStream에서 문자열을 가져오려면 어떻게 해야 합니까? (0) | 2023.04.07 |
"복원할 백업 세트가 선택되지 않았습니다" SQL Server 2012 (0) | 2023.04.07 |