ইতিমধ্যে প্রদত্ত অনেক চমত্কার উত্তরগুলিতে যেমন বলা হয়েছে (বা কমপক্ষে ইঙ্গিত করা হয়েছে), আপনার সাথে কাজ করার জন্য সংখ্যার সেট থাকলেই এই সমস্যাটি সহজেই সমাধান হয়ে যায়।
দ্রষ্টব্য: নিম্নলিখিতটি টি-এসকিউএল কিন্তু এটি কেবলমাত্র ইতিমধ্যে এখানে এবং বৃহত্তর ইন্টারনেটে উল্লিখিত সাধারণ ধারণাগুলির আমার বিশেষ প্রয়োগ। কোডটিকে আপনার পছন্দের উপভাষায় রূপান্তর করা তুলনামূলকভাবে সহজ হওয়া উচিত।
কিভাবে? এই প্রশ্নটি বিবেচনা করুন:
SELECT DATEADD(d, N, '0001-01-22')
FROM Numbers -- A table containing the numbers 0 through N
WHERE N <= 5;
উপরের তারিখের সীমাটি 1/22/0001 - 1/27/0001 উত্পাদন করে এবং অত্যন্ত তুচ্ছ। আছে: উপরে ক্যোয়ারীতে তথ্য 2 চাবি টুকরা শুরুর তারিখ এর 0001-01-22
এবং অফসেট এর 5
। যদি আমরা এই দুটি টুকরো তথ্য একত্রিত করি তবে স্পষ্টতই আমাদের শেষের তারিখ রয়েছে। সুতরাং, দুটি তারিখ দেওয়া, একটি পরিসীমা উত্পন্ন করে এভাবে ভেঙে ফেলা যায়:
দুটি প্রদত্ত তারিখ (অফসেট) এর মধ্যে পার্থক্যটি সন্ধান করুন, সহজ:
-- Returns 125
SELECT ABS(DATEDIFF(d, '2014-08-22', '2014-12-25'))
ABS()
এখানে ব্যবহার নিশ্চিত করে যে তারিখের আদেশটি অপ্রাসঙ্গিক।
সীমিত সংখ্যার সেট তৈরি করুন, খুব সহজ:
-- Returns the numbers 0-2
SELECT N = ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) - 1
FROM(SELECT 'A' AS S UNION ALL SELECT 'A' UNION ALL SELECT 'A')
লক্ষ্য করুন যে আমরা FROM
এখানে কী নির্বাচন করছি তা আসলে আমাদের যত্ন নেই। আমাদের কেবলমাত্র এটির সাথে কাজ করার জন্য একটি সেট প্রয়োজন যাতে আমরা এটিতে সারিগুলির সংখ্যা গণনা করি। আমি ব্যক্তিগতভাবে একটি টিভিএফ ব্যবহার করি, কেউ কেউ সিটিই ব্যবহার করেন, অন্যরা পরিবর্তে একটি সংখ্যা টেবিল ব্যবহার করেন, আপনি ধারণাটি পান get আপনি যে বুঝতে পারছেন এমন সর্বাধিক পারফরম্যান্স সমাধানটি ব্যবহার করার পক্ষে আমি সমর্থন জানাচ্ছি।
এই দুটি পদ্ধতির সংমিশ্রণ আমাদের সমস্যার সমাধান করবে:
DECLARE @date1 DATE = '9001-11-21';
DECLARE @date2 DATE = '9001-11-23';
SELECT D = DATEADD(d, N, @date1)
FROM (
SELECT N = ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) - 1
FROM (SELECT 'A' AS S UNION ALL SELECT 'A' UNION ALL SELECT 'A') S
) Numbers
WHERE N <= ABS(DATEDIFF(d, @date1, @date2));
উপরের উদাহরণটি হ'ল ভয়ঙ্কর কোড তবে এটি দেখায় যে কীভাবে সবকিছু একত্রিত হয়।
আরও মজা
আমার এই ধরণের জিনিসটি অনেক বেশি করা দরকার তাই আমি যুক্তিটি দুটি টিভিএফের মধ্যে আবদ্ধ করে ফেললাম। প্রথমটি বিভিন্ন সংখ্যার পরিসীমা উত্পন্ন করে এবং দ্বিতীয়টি কার্যকারিতাটি বিভিন্ন তারিখ তৈরি করতে ব্যবহার করে। গণিতটি হ'ল এটি নিশ্চিত করা যে ইনপুট অর্ডারটি কোনও বিষয় নয় এবং কারণ আমি এতে উপলব্ধ সংখ্যার সম্পূর্ণ পরিসরটি ব্যবহার করতে চেয়েছিলাম GenerateRangeSmallInt
।
নিম্নলিখিত ফাংশনটি 65536 তারিখের সর্বাধিক পরিসীমা ফেরত দিতে সিপিইউয়ের 16 ডলার সময় নেয়।
CREATE FUNCTION dbo.GenerateRangeDate (
@date1 DATE,
@date2 DATE
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN (
SELECT D = DATEADD(d, N + 32768, CASE WHEN @date1 <= @date2 THEN @date1 ELSE @date2 END)
FROM dbo.GenerateRangeSmallInt(-32768, ABS(DATEDIFF(d, @date1, @date2)) - 32768)
);
GO
CREATE FUNCTION dbo.GenerateRangeSmallInt (
@num1 SMALLINT = -32768
, @num2 SMALLINT = 32767
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN (
WITH Numbers(N) AS (
SELECT N FROM(VALUES
(1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 16
, (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 32
, (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 48
, (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 64
, (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 80
, (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 96
, (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 112
, (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 128
, (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 144
, (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 160
, (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 176
, (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 192
, (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 208
, (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 224
, (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 240
, (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 256
) V (N)
)
SELECT TOP(ABS(CAST(@num1 AS INT) - CAST(@num2 AS INT)) + 1)
N = ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) + CASE WHEN @num1 <= @num2 THEN @num1 ELSE @num2 END - 1
FROM Numbers A
, Numbers B
);