প্রদত্ত পরিসরে প্রধান সংখ্যা numbers


10

সম্প্রতি, আমাকে সমস্ত প্রাথমিক সংখ্যা (1-100) মুদ্রণের জন্য একটি কার্য দেওয়া হয়েছিল। আমি খুব ব্যর্থ সেখানে। আমার কোড:

Create Procedure PrintPrimeNumbers
@startnum int,
@endnum int
AS 
BEGIN
Declare @a INT;
Declare @i INT = 1
(
Select a = @startnum / 2;
WHILE @i<@a
BEGIN
@startnum%(@a-@i)
i=i+1;
)
END

যদিও আমি এটি শেষ না করেই শেষ করেছি, আমি অবাক হয়েছি যে ডেটাবেসগুলিতে (এসকিউএল সার্ভার ২০০৮ আর 2) এ জাতীয় প্রোগ্রাম করা সম্ভব fe

যদি হ্যাঁ, এটি কিভাবে শেষ হতে পারে।


2
প্রদত্ত যে কোনও উত্তর থেকে দূরে সরে যাবেন না, তবে আমি এই বিষয়টি দেখেছি এটি সেরা নিবন্ধ: sqlblog.com/blogs/hugo_kornelis/archive/2006/09/23/…
এরিক ডার্লিং

1 - 100, বা কোনও ব্যাপ্তি এবং 1 - 100 করার লক্ষ্যটি কি কেবল উদাহরণসীমা?
সলোমন রুটজকি

আমার প্রশ্নে, এটি 1 থেকে 100 ছিল I আমি একটি সাধারণ দৃষ্টিভঙ্গি, তারপরে একটি নির্দিষ্ট get
ispostback

উত্তর:


11

"সমস্ত মৌলিক সংখ্যা (1-100)" মুদ্রণের দ্রুততম ও সহজতম উপায়টি হ'ল মূল সংখ্যাটি একটি পরিচিত, সীমাবদ্ধ এবং অপরিবর্তিত মানের মূল্যগুলির সেট ("পরিচিত" এবং "সীমাবদ্ধ" একটিটির মধ্যে রয়েছে তা পুরোপুরি আলিঙ্গন করা a অবশ্যই নির্দিষ্ট পরিসীমা)। স্কেলের এই ক্ষুদ্রতম সময়ে, কেন প্রতিটি সময়ই সিপিইউ নষ্ট করে দেয় যা বহুদিন ধরে জ্ঞাত ছিল এমন একগুচ্ছ মানগুলি গণনা করতে এবং সঞ্চয় করার জন্য খুব কমই কোনও স্মৃতি গ্রহণ করে?

SELECT tmp.[Prime]
FROM   (VALUES (2), (3), (5), (7), (11), (13),
        (17), (19), (23), (29), (31), (37), (41),
        (43), (47), (53), (59), (61), (67), (71),
        (73), (79), (83), (89), (97)) tmp(Prime)

অবশ্যই, যদি আপনার 1 এবং 100 এর মধ্যে মৌলিক সংখ্যাগুলি গণনা করার প্রয়োজন হয় তবে নিম্নলিখিতটি মোটামুটি দক্ষ:

;WITH base AS
(
    SELECT tmp.dummy, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [num]
    FROM   (VALUES (0), (0), (0), (0), (0), (0), (0)) tmp(dummy)
), nums AS
(
    SELECT  (ROW_NUMBER() OVER (ORDER BY (SELECT 1)) * 2) + 1 AS [num]
    FROM        base b1
    CROSS JOIN  base b2
), divs AS
(
    SELECT  [num]
    FROM        base b3
    WHERE   b3.[num] > 4
    AND     b3.[num] % 2 <> 0
    AND     b3.[num] % 3 <> 0
)
SELECT  given.[num] AS [Prime]
FROM        (VALUES (2), (3)) given(num)
UNION ALL
SELECT  n.[num] AS [Prime]
FROM        nums n
WHERE   n.[num] % 3 <> 0
AND     NOT EXISTS (SELECT *
                    FROM divs d
                    WHERE d.[num] <> n.[num]
                    AND n.[num] % d.[num] = 0
                    );

এই ক্যোয়ারীটি কেবল বিজোড় সংখ্যাগুলির পরীক্ষা করে কারণ সংখ্যাগুলি যাইহোক প্রাইম হবে না। এটি 1 - 100 এর সীমাতেও নির্দিষ্ট।

এখন, আপনার যদি একটি গতিশীল পরিসর প্রয়োজন হয় (প্রশ্নের উদাহরণ কোডে যা দেখানো হয়েছে তার সমান) তবে নীচেরটি উপরে থাকা ক্যোয়ারীর অভিযোজন যা এখনও বরং দক্ষ (এটি 1 - 100,000 - 9592 এর পরিসীমা গণনা করেছে) এন্ট্রি - ঠিক 1 সেকেন্ডের নীচে):

DECLARE  @RangeStart INT = 1,
         @RangeEnd INT = 100000;
DECLARE  @HowMany INT = CEILING((@RangeEnd - @RangeStart + 1) / 2.0);

;WITH frst AS
(
    SELECT  tmp.thing1
    FROM        (VALUES (0), (0), (0), (0), (0), (0), (0), (0), (0), (0)) tmp(thing1)
), scnd AS
(
    SELECT  0 AS [thing2]
    FROM        frst t1
    CROSS JOIN frst t2
    CROSS JOIN frst t3
), base AS
(
    SELECT  TOP( CONVERT( INT, CEILING(SQRT(@RangeEnd)) ) )
            ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [num]
    FROM        scnd s1
    CROSS JOIN  scnd s2
), nums AS
(
    SELECT  TOP (@HowMany)
            (ROW_NUMBER() OVER (ORDER BY (SELECT 1)) * 2) + 
                (@RangeStart - 1 - (@RangeStart%2)) AS [num]
    FROM        base b1
    CROSS JOIN  base b2
), divs AS
(
    SELECT  [num]
    FROM        base b3
    WHERE   b3.[num] > 4
    AND     b3.[num] % 2 <> 0
    AND     b3.[num] % 3 <> 0
)
SELECT  given.[num] AS [Prime]
FROM        (VALUES (2), (3)) given(num)
WHERE   given.[num] >= @RangeStart
UNION ALL
SELECT  n.[num] AS [Prime]
FROM        nums n
WHERE   n.[num] BETWEEN 5 AND @RangeEnd
AND     n.[num] % 3 <> 0
AND     NOT EXISTS (SELECT *
                    FROM divs d
                    WHERE d.[num] <> n.[num]
                    AND n.[num] % d.[num] = 0
                    );

আমার পরীক্ষা (ব্যবহার করে SET STATISTICS TIME, IO ON;) দেখায় যে এই ক্যোয়ারী প্রদত্ত অন্য দুটি উত্তরের (এখনও অবধি) তুলনায় ভাল সম্পাদন করেছে:

রেঞ্জ: 1 - 100

Query      Logical Reads       CPU Milliseconds    Elapsed Milliseconds
-------    ----------------    ----------------    -----------------

Solomon      0                 0                   0
Dan        396                 0                   0
Martin     394                 0                   1

রেঞ্জ: 1 - 10,000

Query      Logical Reads       CPU Milliseconds    Elapsed Milliseconds
-------    ----------------    ----------------    -----------------

Solomon        0                   47                170
Dan        77015                 2547               2559
Martin       n/a

রেঞ্জ: 1 - 100,000

Query      Logical Reads       CPU Milliseconds    Elapsed Milliseconds
-------    ----------------    ----------------    -----------------

Solomon            0                 984                996
Dan        3,365,469             195,766            196,650
Martin           n/a

রেঞ্জ: 99,900 - 100,000

দ্রষ্টব্য : এই পরীক্ষাটি চালানোর জন্য আমাকে ড্যানের কোডে একটি বাগ ঠিক করতে @startnumহয়েছিল - ক্যোয়ারিতে সন্ধান করা হয়নি তাই এটি সর্বদা শুরু হয়েছিল 1। আমি Dividend.num <= @endnumসাথে লাইন প্রতিস্থাপন Dividend.num BETWEEN @startnum AND @endnum

Query      Logical Reads       CPU Milliseconds    Elapsed Milliseconds
-------    ----------------    ----------------    -----------------

Solomon       0                   0                   1
Dan           0                 157                 158
Martin      n/a

রেঞ্জ: 1 - 100,000 (আংশিক পুনরায় পরীক্ষা)

99,900 - 100,000 পরীক্ষার জন্য ড্যানের ক্যোয়ারী ঠিক করার পরে, আমি লক্ষ্য করেছি যে আরও যৌক্তিক পাঠ্য তালিকাভুক্ত নেই। সুতরাং আমি এখনও এই প্রয়োগটি স্থির করে দিয়ে এই রেঞ্জটির প্রতিবেদন করেছি এবং দেখতে পেয়েছি যে লজিক্যাল রিডগুলি আবার চলে গেছে এবং সময়গুলি কিছুটা ভাল ছিল (এবং হ্যাঁ, একই সংখ্যক সারি ফিরে এসেছিল)।

Query      Logical Reads       CPU Milliseconds    Elapsed Milliseconds
-------    ----------------    ----------------    -----------------

Dan                0             179,594            180,096

এর উদ্দেশ্য কী ROW_NUMBER() OVER (ORDER BY (SELECT 1))? ROW_NUMBER() OVER ()সমান হবে না ?
লেনার্ট

হাই @Lennart .যদি আপনি ব্যবহার করার প্রচেষ্টা OVER (), আপনি নিম্নলিখিত ত্রুটি পেতে হবে: The function 'ROW_NUMBER' must have an OVER clause with ORDER BY.। এবং, এর সাথে ORDER BY, এটি একটি ধ্রুবক হতে পারে না, সুতরাং একটি ধ্রুবককে ফেরত পাঠানোর উপক্রম।
সলোমন রুটজকি

1
ধন্যবাদ, আমি স্কিল সার্ভারে এই সীমাবদ্ধতা সম্পর্কে অবগত ছিলাম না। এখনই উপলব্ধি করুন
লেনার্ট

আমি যদি DECLARE @RangeStart INT = 999900, @RangeEnd INT = 1000000;এটি ব্যবহার করি তবে DECLARE @RangeStart INT = 9999999900, @RangeEnd INT = 10000000000;এটি সেট করার সাথে সাথেই তা বলবে Msg 8115, Level 16, State 2, Line 1 Arithmetic overflow error converting expression to data type int. Msg 1014, Level 15, State 1, Line 5 A TOP or FETCH clause contains an invalid value.কেন?
ফ্রান্সেস্কো মান্টোভানি

1
@ ফ্রানসেসকো মান্টোভানি এই ত্রুটিটিটি বলছে যে আপনার মানগুলি সীমার বাইরে নয় INT। সর্বোচ্চ মানটি INTধারণ করতে পারে 2,147,483,647, যা আপনার প্রারম্ভিক মান 9,999,999,900 এর চেয়ে ছোট। আপনি কেবলমাত্র কার্যকর করলেও আপনি এই ত্রুটিটি পান DECLARE। আপনি ভেরিয়েবল ডেটাটাইপগুলি পরিবর্তন করতে চেষ্টা করতে পারেন BIGINTএবং এটি কীভাবে হয় তা দেখুন। এটি সমর্থন করার জন্য অন্যান্য ছোটখাটো পরিবর্তন প্রয়োজন হবে। ডেটাটাইপ রেঞ্জের জন্য দয়া করে দেখুন: ইনট, বিগিন্ট, স্মলিন্ট এবং টিনিনেন্ট
সলোমন রুটজকি

7

2-100 (1 টি প্রাথমিক নয়) পরিসরে প্রাথমিক সংখ্যাগুলি ফিরিয়ে দেওয়ার একটি সহজ তবে খুব কার্যকর উপায় নয়

WITH Ten AS (SELECT * FROM (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) V(N)),
     Hundred(N) AS (SELECT T1.N * 10 + T2.N + 1 FROM Ten T1, Ten T2)
SELECT H1.N
FROM   Hundred H1
WHERE  H1.N > 1
       AND NOT EXISTS(SELECT *
                      FROM   Hundred H2
                      WHERE  H2.N > 1
                             AND H1.N > H2.N
                             AND H1.N % H2.N = 0);

আপনি কোনও টেবিলের মধ্যে 2-100 সংখ্যাগুলিও সম্ভাব্যভাবে তৈরি করতে এবং বারবার আপডেট বা মুছে ফেলার মাধ্যমে Eratosthenes এর চালনক প্রয়োগ করতে পারেন ।


4

আমি অবাক হয়েছি যে ডেটাবেসে এই জাতীয় প্রোগ্রাম করা সম্ভব

হ্যাঁ, এটি সম্ভবপর তবে আমি মনে করি না যে টি-এসকিউএল এই কাজের উপযুক্ত সরঞ্জাম। নীচে এই সমস্যার জন্য টি-এসকিউএল-তে একটি সেট-ভিত্তিক পদ্ধতির উদাহরণ রয়েছে।

CREATE PROC dbo.PrintPrimeNumbers
    @startnum int,
    @endnum int
AS 
WITH 
     t4 AS (SELECT n FROM (VALUES(0),(0),(0),(0)) t(n))
    ,t256 AS (SELECT 0 AS n FROM t4 AS a CROSS JOIN t4 AS b CROSS JOIN t4 AS c CROSS JOIN t4 AS d)
    ,t16M AS (SELECT ROW_NUMBER() OVER (ORDER BY (a.n)) AS num FROM t256 AS a CROSS JOIN t256 AS b CROSS JOIN t256 AS c)
SELECT num
FROM t16M AS Dividend
WHERE
    Dividend.num <= @endnum
    AND NOT EXISTS(
        SELECT 1
        FROM t16M AS Divisor
        WHERE
            Divisor.num <= @endnum
            AND Divisor.num BETWEEN 2 AND SQRT(Dividend.num)
            AND Dividend.num % Divisor.num = 0
            AND Dividend.num <= @endnum
    );
GO
EXEC dbo.PrintPrimeNumbers 1, 100;
GO

0

আমরা নীচের কোডটি লিখতে পারি এবং এটি কাজ করে:

CREATE procedure sp_PrimeNumber(@number int)
as 
begin
declare @i int
declare @j int
declare @isPrime int
set @isPrime=1
set @i=2
set @j=2
while(@i<=@number)
begin
    while(@j<=@number)
    begin
        if((@i<>@j) and (@i%@j=0))
        begin
            set @isPrime=0
            break
        end
        else
        begin
            set @j=@j+1
        end
    end
    if(@isPrime=1)
    begin
        SELECT @i
    end
    set @isPrime=1
    set @i=@i+1
    set @j=2
end
end

উপরে আমি মৌলিক সংখ্যাগুলি পাওয়ার জন্য একটি সঞ্চিত পদ্ধতি তৈরি করেছি।

ফলাফলগুলি জানতে, সঞ্চিত প্রক্রিয়াটি সম্পাদন করুন:

EXECUTE sp_PrimeNumber 100

0
DECLARE @UpperLimit INT, @LowerLimit INT

SET @UpperLimit = 500
SET @LowerLimit = 100

DECLARE @N INT, @P INT
DECLARE @Numbers TABLE (Number INT NULL)
DECLARE @Composite TABLE (Number INT NULL)

SET @P = @UpperLimit

IF (@LowerLimit > @UpperLimit OR @UpperLimit < 0 OR @LowerLimit < 0 )
    BEGIN
        PRINT 'Incorrect Range'
    END 
ELSE
    BEGIN
        WHILE @P > @LowerLimit
            BEGIN
                INSERT INTO @Numbers(Number) VALUES (@P)
                SET @N = 2
                WHILE @N <= @UpperLimit/2
                    BEGIN
                        IF ((@P%@N = 0 AND @P <> @N) OR (@P IN (0, 1)))
                            BEGIN
                                INSERT INTO @Composite(Number) VALUES (@P)
                                BREAK
                            END
                        SET @N = @N + 1
                    END
                SET @P = @P - 1
            END
        SELECT Number FROM @Numbers
        WHERE Number NOT IN (SELECT Number FROM @Composite)
        ORDER BY Number
        END
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.