사용자의 입력으로 두 개의 숫자가 있습니다 (예 : 1000
및) 1050
.
별도의 행에서 SQL 쿼리를 사용 하여이 두 숫자 사이의 숫자를 어떻게 생성합니까? 나는 이것을 원한다 :
1000
1001
1002
1003
.
.
1050
답변
VALUES
키워드를 사용하여 비 지속 값을 선택하십시오 . 그런 다음 JOIN
s를 사용 하여 많은 조합을 생성하십시오 (수십만 행 이상으로 확장 가능).
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)
WHERE ones.n + 10*tens.n + 100*hundreds.n + 1000*thousands.n BETWEEN @userinput1 AND @userinput2
ORDER BY 1
더 짧은 대안은 이해하기 쉽지 않습니다.
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
답변
대체 솔루션은 재귀 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의 학점은 전체 기사를 읽는 것이 좋습니다. 루프없이 세트 또는 시퀀스 생성
답변
최근 에이 인라인 테이블 값 함수를 작성 하여이 문제를 해결했습니다. 메모리 및 스토리지 이외의 범위에는 제한이 없습니다. 테이블에 액세스하지 않으므로 일반적으로 디스크 읽기 또는 쓰기가 필요하지 않습니다. 각 반복마다 지수 적으로 결합 값을 추가하므로 매우 넓은 범위에서도 매우 빠릅니다. 내 서버에서 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'));
교차 적용 조인을 사용하여 테이블의 값을 기반으로 레코드를 분할 할 수 있습니다. 예를 들어 테이블의 시간 범위에서 1 분마다 레코드를 작성하려면 다음과 같이 할 수 있습니다.
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
답변
내가 사용한 가장 좋은 옵션은 다음과 같습니다.
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
이것을 사용하여 수백만 개의 레코드를 생성했으며 완벽하게 작동합니다.
답변
그것은 나를 위해 작동합니다!
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)
살루도.