কীভাবে দুটি সংখ্যার মধ্যে বিস্তৃত সংখ্যা তৈরি করতে হয়?


141

ব্যবহারকারীর কাছ থেকে ইনপুট হিসাবে আমার কাছে দুটি সংখ্যা রয়েছে, উদাহরণস্বরূপ 1000এবং 1050

আমি কীভাবে এই দুটি সংখ্যার মধ্যে পৃথক সারিগুলিতে একটি বর্গ কোয়েরি ব্যবহার করে সংখ্যাগুলি তৈরি করতে পারি? আমি এটা চাই:

 1000
 1001
 1002
 1003
 .
 .
 1050

উত্তর:


159

VALUESকীওয়ার্ড সহ অ-অব্যাহত মানগুলি নির্বাচন করুন । তারপরে JOINপ্রচুর এবং প্রচুর সংমিশ্রণ তৈরি করতে এস ব্যবহার করুন (কয়েক হাজার সারি এবং এর বাইরেও কয়েক হাজার সৃজন তৈরি করতে বাড়ানো যেতে পারে)।

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

Demo

একটি সংক্ষিপ্ত বিকল্প, এটি বোঝা তত সহজ নয়:

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

Demo


13
এটি একটি
চমত্কারভাবে

9
আপনি সিনট্যাক্স ব্যাখ্যা করতে পারেন? ভি (এন) কী?
রাফি

2
@ রাফি ভি (এন) এবং শত (এন) ইত্যাদি হ'ল টেবিল এবং কলামের নাম / উপকরণ
টোভন-হা

106

একটি বিকল্প সমাধান recursive সিটিই হয়:

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)

4
ভিউ সংজ্ঞাতে ম্যাক্সক্র্যাসিউশন বিকল্পটি ব্যবহার করার চেষ্টা করবেন না। পরিবর্তে আপনাকে অবশ্যই * CTE_VIEW বিকল্প থেকে 100 টি নির্বাচন করুন (MAXRECURSION 10000) - সমস্যাযুক্ত, যদি আপনি ক্লায়েন্ট অ্যাপ্লিকেশনটি ভিউটি যেমন দেখায় তেমন ব্যবহার করতে চান।
টিভিডিএইচ

4
এখানে সর্বাধিক ম্যাক্সেরেকারশন সেট করা আছে 32767 (এসকিউএল সার্ভারে 2012)।
বিপিরোভ

4
কেবল স্পষ্ট করে বলতে গেলে, আপনার যদি 32767 এর বেশি সংখ্যক পুনরাবৃত্তি প্রয়োজন হয়, তবে এটি 0 তে সেট করা যেতে পারে যার অর্থ নোম্যাক্স,
জয়ভি

2
এই উত্তরের জন্য এখানে ডেমো রয়েছে
stomy

7
আমি এই উত্তরটিকে অন্যের সাথে তুলনা করেছি এবং এক্সিকিউশন পরিকল্পনাটি দেখায় যে এই উত্তরটি ( কমপক্ষে ক্যোয়ারী ব্যয় রয়েছে এবং ) সবচেয়ে দ্রুত।
stomy

39
SELECT DISTINCT n = number 
FROM master..[spt_values] 
WHERE number BETWEEN @start AND @end

Demo

নোট করুন যে এই টেবিলটিতে সর্বাধিক 2048 রয়েছে কারণ তখন সংখ্যার ফাঁক রয়েছে।

সিস্টেম ভিউ ব্যবহার করে এখানে কিছুটা ভাল পদ্ধতির (এসকিউএল-সার্ভার ২০০৫ থেকে):

;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;

Demo

বা একটি কাস্টম একটি নম্বর টেবিল ব্যবহার করুন। অ্যারন বারট্র্যান্ডের ক্রেডিট, আমি পুরো নিবন্ধটি পড়ার পরামর্শ দিই : লুপগুলি ছাড়াই একটি সেট বা ক্রম তৈরি করুন


2
@ ব্যবহারকারী 3211705: আমার সম্পাদনাটি লক্ষ্য করুন, এই টেবিলটিতে সর্বাধিক 2048 রয়েছে I আমি পুরো নিবন্ধটি পড়ার পরামর্শ দিই।
টিম শেমলেটার

3
আমি মনে করি আপনি যোগ WHERE type = 'P'এবং এড়াতে পারবেনSELECT DISTINCT
সালমান এ

1
আপনার প্রথম "ডেমো" লিঙ্কটি আমাকে বলে String index out of range: 33
চলেছে

1
তুমি ঠিক বলছো. তবে এটি স্কেলফিডলের একটি সমস্যা বলে মনে হচ্ছে। এটি আপনার ডিবিতে কাজ করে?
টিম শ্মেলেটার

4
দ্রুত দ্রষ্টব্য, এই জাতীয় ক্রস-ডাটাবেস অনুসন্ধানগুলি এসকিউএল অ্যাজুরে
কাইরেন জনস্টোন

33

আমি সম্প্রতি এই খুব সমস্যা সমাধানের জন্য এই ইনলাইন টেবিলের মূল্যবান ফাংশনটি লিখেছি। এটি মেমরি এবং সঞ্চয়স্থান ব্যতীত অন্য সীমার মধ্যে সীমাবদ্ধ নয়। এটি কোনও টেবিল অ্যাক্সেস করে না তাই সাধারণত ডিস্ক পড়া বা লেখার প্রয়োজন নেই। এটি প্রতিটি পুনরাবৃত্তিতে তাত্ক্ষণিকভাবে মানগুলিতে যোগ হয় তাই এটি খুব বড় ব্যাপ্তির জন্যও খুব দ্রুত। এটি আমার সার্ভারে পাঁচ সেকেন্ডে দশ মিলিয়ন রেকর্ড তৈরি করে। এটি নেতিবাচক মানগুলির সাথেও কাজ করে।

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

1
বাহ, সেই প্রাথমিক ক্যোয়ারীটি দ্রুত। উপরে পোস্ট করা সিএলআর সমাধানের চেয়ে অনেক দ্রুত। ধন্যবাদ!
ডেরেক ডিন

1
ভাল - আমি এসকিউএল সার্ভার ২০০৮ এ এখনও একটি ক্লায়েন্ট রয়েছি এবং এটি কেবল আমার প্রয়োজন ছিল! খুব চালাক!
এসটিএলডিভ

1
এটি 1-100 এর জন্য কাজ করে তবে ব্যর্থ হয়। এমনকি আপনার 5-500 উত্পন্ন করার উদাহরণটি আমার পক্ষে কাজ করে না, এটি 5, 21, ... 484, 500 দেখায়
রেজ. নেট নেট

3
আপনি যদি এটি বাছাই করতে চান তবে আপনাকে ধারা দ্বারা একটি আদেশ যোগ করতে হবে:SELECT X FROM fn_ConsecutiveNumbers(5, 500) ORDER BY X;
ব্রায়ান প্রেসার

29

আমি সবচেয়ে ভাল বিকল্পটি ব্যবহার করেছি:

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

আমি এটি ব্যবহার করে কয়েক মিলিয়ন রেকর্ড তৈরি করেছি এবং এটি নিখুঁত কাজ করে।


2
এটি এখানে সর্বাধিক মার্জিত সমাধান, তবে আমি মনে করি এটি অনেকের পক্ষে এটি বুঝতে অসুবিধা হয় (আমি এটি মাস্টার.সিস.সাল_কলামগুলি দিয়েই করছিলাম)। @ এসটিএল ডেভেলপার, হ্যাঁ এটি ২০০৮ এবং তার পরে কাজ করে।
Cetin Basoz

13

এটা আমার জন্য কাজ!

select top 50 ROW_NUMBER() over(order by a.name) + 1000 as Rcount
from sys.all_objects a

2
দুর্দান্ত এক-লাইনার - তবে সতর্ক হতে হবে যে সারিগুলির সর্বাধিক সংখ্যার উপর নির্ভর করবে sys.all_objects- ছোট ব্যাপ্তি <2000 আইটেমের জন্য, এটি কোনও সমস্যা নয়। নিশ্চিত না এটির অনুমতির সমস্যা থাকবে কিনা? পরীক্ষার ডেটাগুলির একটি ব্যাচ দ্রুত তৈরির জন্য উপযুক্ত।
freedomn-M

@ फ्रीডেন-এম সর্বাধিক সারি বাড়ানোর এক উপায় হ'ল একটি স্ব-ক্রস জয়েন করা। select top 50 ROW_NUMBER() over(order by a.name) + 1000 as Rcount from sys.all_objects a, sys.all_objects b। যেখানে আমি কেবল আগে 2384 সারি তৈরি করতে পারতাম, এখন আমি 5683456 সারি তৈরি করতে পারি।
ক্লিকার

9

সবচেয়ে ভাল উপায় হ'ল পুনরাবৃত্তির উর্ধ্বতন ব্যবহার করা।

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)

saludos।


1
এটি খুব দরকারী ছিল। আমি কোডটি পরিবর্তন করেছি যাতে আমি 100.000 সারি সন্নিবেশ করতে পারি। আমার সমাধানের সাথে এটি 13 মিনিটের মতো লেগেছিল; আপনার ব্যবহার করে, এটি পাঁচ সেকেন্ড সময় নিয়েছে। মুচিসিমাস গ্রাসিয়াস।
চথুলহু

2
প্রকৃতপক্ষে, রিকার্সিভ সিটিই গণনা করার সবচেয়ে খারাপ উপায়গুলির মধ্যে একটি। এমনকি লেনদেনের সময় ওয়েল লুপের দ্বারাও তারা মারধর করতে পারে এবং লুপটি আরও কম পাঠ্য উত্পাদন করতে পারে। সিসিটিই পদ্ধতি (ক্যাসকেডিং সিটিই, মূলত ইটিজিক বেন-গান দ্বারা নির্মিত) অনেক দ্রুত এবং শূন্য পাঠের উত্পাদন করে।
জেফ মোডেন

9
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

1
এটি @ জাভির উত্তর চেয়ে আলাদা?
নোয়েল

1
হ্যাঁ শর্তে এটির নাম +1 <1050 হিসাবে উল্লিখিত যা কেবল 1049 পর্যন্ত মুদ্রণ করবে।
সওবারানী কার্তিক্যয়ন

2
বিদ্যমান উত্তরের একটি সম্পাদনা (বা মন্তব্য) যা একই প্রয়োজনীয়, সম্পূর্ণ নতুন উত্তরের চেয়ে আরও বেশি মান সরবরাহ করতে পারে।
নোয়েল

7

আপনার সার্ভারে সিএলআর অ্যাসেম্বলি ইনস্টল করতে আপনার যদি সমস্যা না হয় তবে একটি ভাল বিকল্পটি .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)

1
আমি এই সমাধানটি চেষ্টা করে দেখলাম এবং এটি খুব দ্রুত কাজ করে না, এটি ভালভাবে কাজ করে। আপনি যদি মাত্র ১,০০০ নম্বর বা সম্ভবত 10,000 জেনারেট করে থাকেন তবে এটি মোটামুটি দ্রুত। আপনি যদি আমার মতো হন এবং কয়েক বিলিয়ন সংখ্যা তৈরি করতে হয় তবে এসকিউএল সিএলআরের তুলনায় নীচে ব্রায়ান প্রেসার এর সমাধান অবিশ্বাস্যভাবে দ্রুত।
ডেরেক ডিন

2
নিবন্ধন করুন আমি মনে করি যে এটিই সেরা সমাধান কারণ এটি তৈরি করা এবং ব্যবহার করা সহজ (এবং আপনি যেমন বলছেন তত দ্রুত)। আমার ক্ষেত্রে ইতিমধ্যে আমার কাছে স্ট্রিং সংশ্লেষের জন্য একটি অ্যাসেম্বলি ছিল তাই আমি এটি কেবল সেখানে যুক্ত করেছি।
অ্যালেক্সডেভ

1
আমি পাশাপাশি একটি বিদ্যমান সমাবেশ ছিল এবং উভয় পদ্ধতি চেষ্টা করেছিলাম। তারিখগুলিতে যোগ করার জন্য আমি একটি অনির্দিষ্ট সংখ্যার সংখ্যা উত্পন্ন করছি (মূলত, আমি আমাদের অভ্যন্তরীণ আবেদনের জন্য তারিখ উত্পন্ন করার জন্য এসকিউএল সার্ভার এজেন্ট সময়সূচীটি পুনরায় তৈরি করেছি, এবং একাধিক বছরের উত্পন্ন করার জন্য 100 স্তরের পুনরাবৃত্তি এটি কাটছে না was ডেটটাইমস, সম্ভবত দ্বিতীয় থেকে নীচে)), তাই আমি এই থ্রেড থেকে একাধিক সমাধানের পুঙ্খানুপুঙ্খভাবে পরীক্ষা করতে সক্ষম হয়েছি। আমি আপনার অবদান প্রশংসা করি!
ডেরেক ডিন

7

নতুন কিছু নয় তবে আমি ব্রায়ান প্রেসার সমাধানটি আবার চোখের সামনে আরও সহজ করে লিখলাম, এটি কারওর পক্ষে কার্যকর হতে পারে (এমনকি এটি কেবল ভবিষ্যতের আমার জন্যও):

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

1
আমি বিশ্বাস করি আপনি একটি সুন্দর অ্যালগরিদমের সংমিশ্রণটি কিছু নিখুঁত সুন্দর কোডে মিশ্রিত করেছেন।
ক্লে

1
ফলাফলগুলি একটি অদ্ভুত তবে বিশৃঙ্খলাযুক্ত নয় ordered এটি 5 থেকে 500 পর্যন্ত পরিসীমাতে পরীক্ষা করুন It এটি 5,21,37, ..., 245,6,22, ... ফেরত দেয় কীভাবে অর্ডারিং কার্য সম্পাদনকে প্রভাবিত করবে আপনি জানেন? ভিত্তিক সমাধানগুলির মধ্যে ROW_NUMBER()সেই সমস্যা নেই।
প্রজেমেস্লাও রিমিন

1
আমি কোনও বিশেষজ্ঞ নই তবে স্বজ্ঞাতভাবে আমি অনুমান করব যে এসকিউএল সার্ভারের সমস্ত ফলাফল মেমরিতে রাখা উচিত এবং তাদের আরও বেশি মেমরির ব্যবহার এবং বিলম্বিত প্রতিক্রিয়াটি ফিরে আসার আগে কেবল ফলাফলগুলি আসার বিরোধিতা করার আগে তাদের অর্ডার করতে হবে।
গিলাইউমূম্বে

6

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)

5

কার্টেসিয়ান পণ্য সম্পর্কিত সমস্ত উল্লেখ মুছে ফেলা এবং 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

এটি একটি সিটিই এর ভিতরে আবৃত করুন এবং পছন্দসই সংখ্যাগুলি নির্বাচন করার জন্য যেখানে একটি ধারা যুক্ত করুন:

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

1
ROW_NUMBER কেবল ১ থেকে শুরু হয় আমরা কীভাবে আপনার পদ্ধতির সাহায্যে শূন্য থেকে শুরু করতে পারি?
stomy

2
@stomy SELECT ROW_NUMBER() OVER (...) - 1 AS n। কিছু ক্ষেত্রে এটি কর্মক্ষমতা হারাতে পারে।
সালমান এ

4

এখানে বেশ কয়েকটি অনুকূল এবং সামঞ্জস্যপূর্ণ সমাধান:

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
;

1
এই পদ্ধতিটি কোনওভাবে সহজভাবে selectইনগিংয়ের চেয়ে ভাল where spt_values.number between @min and @max?
আন্ডারস্কোর_১

2
নকল সংখ্যাগুলি প্রতিরোধ করতে টাইপ = 'পি' ফিল্টারটি প্রয়োজন। এই ফিল্টারটি দিয়ে টেবিলটি 0 - 2047 নম্বরগুলি ফিরিয়ে দেবে So সুতরাং "@ মিমি এবং @ ম্যাক্সের মধ্যে নম্বর" ফিল্টারটি যতক্ষণ চলকগুলি এই সীমার মধ্যে থাকবে ততক্ষণ কাজ করবে। আমার সমাধান আপনাকে পূর্ণসংখ্যার পরিসীমা (-2,147,483,648) - (2,147,483,647) এর মধ্যে 2048 সারি পর্যন্ত পেতে দেয়।
jumxozizi

1
উপরের যুক্তি কেবল তখনই কার্যকর যখন সর্বাধিক এবং সর্বনিম্ন সংখ্যার মধ্যে পার্থক্য 2048 এর চেয়ে কম এবং একবার সর্বোচ্চ সময়ে 2048 রেকর্ড করতে পারে
স্মার্ট 3003

4

আমি জানি যে আমি 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

আমরা যদি চাই এমন রেঞ্জটি জানি তবে আমরা @ ওপার এবং @ কমের মাধ্যমে এটি নির্দিষ্ট করতে পারি। শীর্ষের সাথে যোগদানের ইঙ্গিত রিমোটকে একত্রিত করে আমরা কেবলমাত্র মূল্যবোধের উপসেট গণনা করতে পারি যা কিছু নষ্ট না করেই আমরা চাই।

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

যোগদানের ইঙ্গিতটি REMOTE অপ্টিমাইজারটিকে প্রথমে যোগদানের ডান দিকে তুলনা করতে বাধ্য করে। প্রত্যেকটি যোগদানকে বেশিরভাগ থেকে কমপক্ষে উল্লেখযোগ্য মান থেকে REMOTE হিসাবে নির্দিষ্ট করে, যোগদানটি নিজেই সঠিকভাবে উপরের দিকে গণনা করবে। WHERE দিয়ে ফিল্টার করার দরকার নেই বা অর্ডার দিয়ে সাজান।

যদি আপনি এই সীমাটি বাড়াতে চান তবে আপনি ক্রমবর্ধমান উচ্চতর অর্ডারের সাথে অতিরিক্ত যোগ যোগ দিতে চালিয়ে যেতে পারেন, যতক্ষণ না তাদের এফআরএম ধারাটিতে সর্বাধিক থেকে তাত্পর্যপূর্ণভাবে অর্ডার করা হয়।

মনে রাখবেন যে এটি এসকিউএল সার্ভার ২০০৮ বা তার চেয়ে বেশি এর জন্য নির্দিষ্ট একটি ক্যোয়ারী।


1
সত্যিই খুব সুন্দর. একই কৌশলটি ব্রায়ান প্রেসার-এর দুর্দান্ত উত্তর এবং গিলাইউম ৮86's এর সুদৃশ্য লেখার ক্ষেত্রেও প্রয়োগ করা যেতে পারে।
ক্লে

3

এটিও করবে

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

3

রান কোয়েরি করার সময় সেরা গতি

DECLARE @num INT = 1000
WHILE(@num<1050)
begin
 INSERT  INTO [dbo].[Codes]
    (   Code
    ) 
    VALUES (@num)
    SET @num = @num + 1
end

3

ক্ষতিকারক আকারে পুনরাবিপন্ন সিটিই (এমনকি 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

ওপি অনুসারে, আমি মনে করি @startnumএবং endnumব্যবহারকারীর দ্বারা ইনপুট হওয়া উচিত?
জেসি

2

আমাকে অনুরূপ পদ্ধতি ব্যবহার করে ডেটাবেজে চিত্র ফাইলপথ প্রবেশ করতে হয়েছিল। নীচের ক্যোয়ারীটি ভাল কাজ করেছে:

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

2

এটি আমি যা করি এটি বেশ দ্রুত এবং নমনীয় এবং প্রচুর কোড নয়।

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;

মনে রাখবেন যে (অ্যাকাউন্ট দ্বারা অর্ডার) একটি ডামি। এটি ROW_NUMBER () এর একটি ORDER বাই প্রয়োজন ছাড়া কিছুই করে না।

সম্পাদনা : আমি বুঝতে পেরেছিলাম যে আসল প্রশ্নটি ছিল 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;

1
এটি ছিল খুব দ্রুত - এবং নমনীয়। আমার প্রয়োজনের জন্য ভাল কাজ করেছেন।
অ্যান্ড্রুবাঞ্জো 1968

1
-- 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

এটি কেবলমাত্র সিক্যুয়েন্সগুলির জন্য কাজ করে যতক্ষণ কিছু অ্যাপ্লিকেশন সারণীতে সারি থাকে। ধরুন আমি ১.১০০ থেকে ক্রম চাই, এবং কলাম (সংখ্যাসূচক বা স্ট্রিং ধরণের) foo.bar সহ অ্যাপ্লিকেশন টেবিল dbo.foo আছে:

select 
top 100
row_number() over (order by dbo.foo.bar) as seq
from dbo.foo

ধারা অনুসারে একটি অর্ডারে উপস্থিত থাকা সত্ত্বেও, dbo.foo.bar এর স্বতন্ত্র বা এমনকি নন-নাল মান থাকতে হবে না।

অবশ্যই, এসকিউএল সার্ভার ২০১২ এর সিকোয়েন্স অবজেক্ট রয়েছে, সুতরাং সেই পণ্যটিতে একটি প্রাকৃতিক সমাধান রয়েছে।


1

আমি এখানে যা এলাম তা এখানে:

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 পর্যন্ত মান উত্পন্ন করে। যোগদানের শর্তগুলি এটি ছোট মানগুলির জন্য দ্রুত রাখে।


1

এটি আমার ডিভি সার্ভারে 36 সেকেন্ডের মধ্যে আমার জন্য সম্পন্ন হয়েছে। ব্রায়ানের উত্তরের মতো, ক্যোয়ারীর মধ্যে থেকেই পরিসরে ফিল্টারিংয়ের উপর দৃষ্টি নিবদ্ধ করা গুরুত্বপূর্ণ; একটি বিটউইন এখনও নীচে আবদ্ধ হওয়ার আগে সমস্ত প্রাথমিক রেকর্ড তৈরি করার চেষ্টা করে যদিও এটিগুলির প্রয়োজন নেই doesn't

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 একটি বড়গুরু , সুতরাং এটি ব্যবহার করে এমন কোনও পদ্ধতির সাথে আমরা 2 ^^ 64 (== 16 ^^ 16) উত্পাদিত রেকর্ডের বেশি যেতে পারি না। এই কোয়েরিটি তাই উত্পন্ন মানগুলিতে একই ওপরের সীমাটিকে সম্মান করে।


1

এটি পদ্ধতিগত কোড এবং একটি সারণী-মূল্যবান ফাংশন ব্যবহার করে। ধীর, তবে সহজ এবং অনুমানযোগ্য।

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

এটি একটি টেবিল, যাতে আপনি এটি অন্যান্য ডেটার সাথে যুক্ত হতে পারেন। সময়ের মানগুলির সংলগ্ন ধারাটি নিশ্চিত করতে আমি প্রায়শই এই ফাংশনটি সময়, দিন ইত্যাদির মাধ্যমে কোনও গ্রুপের বিপরীতে যোগদানের বাম দিক হিসাবে ব্যবহার করি।

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
(...)

পারফরম্যান্স আনইনস্পায়ারিং (এক মিলিয়ন সারিগুলির জন্য 16 সেকেন্ড) তবে অনেকগুলি উদ্দেশ্যে যথেষ্ট ভাল।

SELECT count(1) FROM [dbo].[Sequence] (
   1000001
  ,2000000)
GO

1

ওরাকল 12 সি; দ্রুত কিন্তু সীমাবদ্ধ:

select rownum+1000 from all_objects fetch first 50 rows only;

দ্রষ্টব্য : সমস্ত_জেক্ট ভিউয়ের সারি গণিতে সীমাবদ্ধ;


1

সমাধানটি আমি বেশ কিছুদিন ধরে বিকশিত করেছি এবং ব্যবহার করেছি (অন্যের অংশীদারি কাজে কিছুটা চালিয়ে যাওয়া) কমপক্ষে পোস্ট হওয়া একটির মতোই। এটি কোনও সারণী রেফারেন্স করে না এবং 1048576 মানের (2 ^ 20) অবধি অরসেটেড পরিসীমা প্রদান করে এবং ইচ্ছা করলে negativeণাত্মকগুলি অন্তর্ভুক্ত করতে পারে। প্রয়োজনে আপনি অবশ্যই ফলাফলটি বাছাই করতে পারেন। এটি বেশ দ্রুত চলে, বিশেষত ছোট রেঞ্জগুলিতে।

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
)

1
;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

1

আমি এই থ্রেডটি পড়ে নিচের ফাংশনটি করেছি। সহজ এবং দ্রুত:

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)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.