প্রতি মাসের তৃতীয় শুক্রবার নির্ধারণ করুন


16

এসকিউএল সার্ভারে "1.1.1996 - 30.8.2014" তারিখের পরিসরের জন্য আমাকে "প্রত্যেক মাসের তৃতীয় শুক্রবার" তারিখগুলি নির্ধারণ করতে হবে।

আমি সংমিশ্রণ ব্যবহার করা উচিত আশা DENSE_RANK()এবং PARTITION BY()সেট "র্যাঙ্ক = 3" করা হয়েছে। তবে আমি এসকিউএল-এ নতুন এবং সঠিক কোডটি খুঁজে পেতে অক্ষম।

উত্তর:


26

প্রদত্ত:

  • শুক্রবারকে "শুক্রবার" বলা হয়
  • মাসের তৃতীয় শুক্রবার সর্বদা মাসের 15 তম-21 শে থেকে নেমে আসবে

    select thedate
    from yourtable
    where datename(weekday, thedate) = 'Friday'
    and datepart(day, thedate)>=15 and datepart(day, thedate)<=21;

এছাড়াও আপনি ব্যবহার করতে পারে weekdayসঙ্গে datepart(), কিন্তু এটা একটি নাম আইএমও সঙ্গে আরো পাঠযোগ্য নয়। স্ট্রিং তুলনা স্পষ্টতই ধীর হবে যদিও।


14

কোনও ভাষা / সংস্কৃতি স্বতন্ত্র উত্তর পেতে, আপনাকে সপ্তাহের বিভিন্ন দিনের নাম এবং সপ্তাহের শুরুতে অ্যাকাউন্ট করতে হবে।

ইতালিতে শুক্রবার "ভেনেরডে" এবং সপ্তাহের প্রথম দিন সোমবার, মার্কিন রবিবারের মতো নয়।

1900-01-01 সোমবার ছিল তাই আমরা লোকাল-স্বাধীন ফ্যাশনে সপ্তাহের দিন গণনা করতে এই তথ্যটি ব্যবহার করতে পারি:

WITH dates AS (
    SELECT DATEADD(day, number, GETDATE()) AS theDate
    FROM master.dbo.spt_values
    WHERE type = 'P'
)
SELECT theDate, DATENAME(dw, theDate), DATEPART(dw, theDate)
FROM dates
WHERE DATEDIFF(day, '19000101', theDate) % 7 = 4
    AND DATEPART(day, thedate)>=15 and DATEPART(day, thedate)<=21;

12

আরেকটি উপায়, এটি ফিলের উত্তরটিকে বেস হিসাবে ব্যবহার করে এবং বিভিন্ন সেটিংয়ের যত্ন নেয়:

select thedate
from yourtable
where (datepart(weekday, thedate) + @@DATEFIRST - 2) % 7 + 1 = 5   -- 5 -> Friday
  and (datepart(day, thedate) - 1) / 7 + 1 = 3 ;                   -- 3 -> 3rd week

5কোড (যদি আপনি শুক্রবার ছাড়া অন্য কোনো কাজের দিন চান) (যেমন একই হতে হবে SET DATEFIRSTকোডগুলি):

1 for Monday
2 for Tuesday
3 for Wednesday
4 for Thursday
5 for Friday
6 for Saturday
7 for Sunday

ভাষা সেটিংসের মুখে সুরক্ষিত রাখতে আপনি কেবল "পরিচিত ভাল" তারিখটি ব্যবহার করতে পারেন। উদাহরণস্বরূপ, শুক্রবারের জন্য সন্ধান করা হলে, একটি ক্যালেন্ডার চেক করুন এবং দেখুন যে 2 শে জানুয়ারী 2015 শুক্রবার ছিল। প্রথম তুলনাটি তখন লেখা যেতে পারে:

DATEPART(weekday,thedate) = DATEPART(weekday,'20150102') --Any Friday

পিটার লারসন দ্বারা এক মাসের নবম সপ্তাহের দিন কীভাবে পাবেন তাও দেখুন ।


4

আমি আসলে এখানে এই ধরণের গণনা সম্পর্কে একটি নিবন্ধ লিখেছিলাম

মূলত, আপনি যে কোনও তারিখের ব্যাপ্তিতে প্রতি মাসের ২ য় শুক্র খুঁজে পেতে নিম্নলিখিত কোডগুলি ব্যবহার করতে পারেন

USE TEMPDB
set nocount on;
IF OBJECT_ID('dbo.#t') is not null 
 DROP TABLE dbo.#t;
CREATE TABLE #t ([Date] datetime,
  [Year] smallint, [Quarter] tinyint, [Month] tinyint
, [Day] smallint -- from 1 to 366 = 1st to 366th day in a year
, [Week] tinyint -- from 1 to 54 = the 1st to 54th week in a year; 
, [Monthly_week] tinyint -- 1/2/3/4/5=1st/2nd/3rd/4th/5th week in a month
, [Week_day] tinyint -- 1=Mon, 2=Tue, 3=Wed, 4=Thu, 5=Fri, 6=Sat, 7=Sun
);
GO
USE TEMPDB
-- populate the table #t, and the day of week is defined as
-- 1=Mon, 2=Tue, 3=Wed, 4=Thu,5=Fri, 6=Sat, 7=Sun
;WITH   C0   AS (SELECT c FROM (VALUES(1),(1)) AS D(c)),
  C1   AS (SELECT 1 AS c FROM C0 AS A CROSS JOIN C0 AS B),
  C2   AS (SELECT 1 AS c FROM C1 AS A CROSS JOIN C1 AS B),
  C3   AS (SELECT 1 AS c FROM C2 AS A CROSS JOIN C2 AS B),
  C4   AS (SELECT 1 AS c FROM C3 AS A CROSS JOIN C3 AS B), 
  C5   AS (SELECT 1 AS c FROM C4 AS A CROSS JOIN C3 AS B),
  C6   AS (select rn=row_number() over (order by c)  from C5),
  C7   as (select [date]=dateadd(day, rn-1, '19000101') FROM C6 WHERE rn <= datediff(day, '19000101', '99991231')+1)

INSERT INTO #t ([year], [quarter], [month], [week], [day], [monthly_week], [week_day], [date])
SELECT datepart(yy, [DATE]), datepart(qq, [date]), datepart(mm, [date]), datepart(wk, [date])
     , datediff(day, dateadd(year, datediff(year, 0, [date]), 0), [date])+1
  , datepart(week, [date]) -datepart(week, dateadd(month, datediff(month, 0, [date]) , 0))+1
  , CASE WHEN datepart(dw, [date])+@@datefirst-1 > 7 THEN (datepart(dw, [date])+@@datefirst-1)%7
         ELSE datepart(dw, [date])+@@datefirst-1 END
 , [date]
FROM C7
    --where [date] between '19900101' and '20990101'; -- if you want to populate a range of dates
GO

select convert(char(10), [Date], 120) 
from #t
where Monthly_week=3
and week_day=5
and [date] between '2015-01-01' and '2015-12-31' -- change to your own date range

2

হ্যাঁ, আমি জানি এটি পুরানো পোস্ট। ভেবেছিলাম বয়সকালেও আমি জিনিসগুলিতে একটি আলাদা স্লেট সরবরাহ করব। হি ... এবং আমার ক্ষমা চাই আমি ঠিক বুঝতে পেরেছি যে @ জ্যাও উপরোক্ত পোস্টগুলি প্রায় সদৃশ করেছি।

ওপির মূল প্রশ্নের বর্তমান সম্পাদনার ভিত্তিতে, আমি বুঝতে পারি না যে লোকেরা উত্তর কেন পোস্ট করেছে।

সম্পাদনাগুলি সন্ধান করে আমি মূল প্রশ্নটি পেয়েছি এবং এটি নীচে পোস্ট করেছি ...

আমার একটি এসকিউএল ডাটাবেসে উদাহরণস্বরূপ 1.1.1996 - 30.8.2014 থেকে শুরু করে টেবিল "db.dbo.destable" সহ have

এসকিউএল-এ এই তারিখের সীমাটির জন্য আমার যে তারিখগুলি "প্রতি মাসের তৃতীয় শুক্রবার" রয়েছে তা নির্ধারণ করতে হবে।

আমি আশা করি "র‌্যাঙ্ক = 3" সেট করতে আমার "DENSE_RANK ()" এবং "পার্টিশন বাই ()" এর সংমিশ্রণটি ব্যবহার করা উচিত। তবে আমি এসকিউএল-এ নতুন এবং সঠিক কোডটি খুঁজে পেতে অক্ষম।

আপনি কি এই সমস্যার সমাধান করতে পারেন?

বোল্ডিংয়ের মাধ্যমে আমি যে মূল প্রশ্নের জোর দিয়েছি তা এর মূল বলে মনে হচ্ছে। আমি অবশ্যই ভুল হতে পারি তবে এটি আমার কাছে মনে হয় যে ওপি বলেছিল যে তার কাছে "ডিবিও ডেটেস্টেবল" নামে একটি "ক্যালেন্ডার" টেবিল রয়েছে এবং আমার কাছে এটি একটি বিশাল পরিমাণে পার্থক্য তৈরি করেছে এবং আমি এখন বুঝতে পেরেছি কেন উত্তরগুলির অনেকগুলি তারা কী সেই তারিখগুলি অন্তর্ভুক্ত করছে যার সাথে তারিখগুলি তৈরি হয়েছিল কারণ এটি 10 ​​নভেম্বর পোস্ট করা হয়েছিল ... প্রশ্নটির চূড়ান্ত সম্পাদনার একদিন পরে, যা "ডিবিও.ডেস্টেটেবল" -র রেফারেন্সের চূড়ান্ত স্বত্বগুলি সরিয়ে দিয়েছে।

যেমনটি আমি বলেছিলাম, আমি ভুল হতে পারি তবে এখানে মূল প্রশ্নের আমার ব্যাখ্যা।

আমার কাছে একটি "ক্যালেন্ডার" টেবিল রয়েছে যার নাম "ডিবিও ডেটেস্টেবল"। সেই টেবিলের আওতায় থাকা কোনও তারিখের পরিসর দেওয়া, আমি কীভাবে সেই তারিখের মধ্যে প্রতি মাসের তৃতীয় শুক্রবারের তারিখগুলি ফিরিয়ে দিতে পারি?

যেহেতু এটি করার জন্য প্রচলিত পদ্ধতিগুলি ইতিমধ্যে কভার করা হয়েছে, তাই আমি এমন একটি বিকল্প যুক্ত করব যা কারওর জন্য সহায়ক হতে পারে।

আসুন এমন কয়েকটি কলামের অনুকরণ করুন যা আমি মনে করি যে ওপি ইতিমধ্যে তার টেবিলে থাকবে। অবশ্যই, আমি কলামের নামগুলি অনুমান করছি। আপনার "ক্যালেন্ডার" টেবিলের জন্য সমতুল্য কলামগুলি যাই হোক না কেন তা জমা দিন। এছাড়াও, আমি টেম্পডিবিতে এগুলি করছি তাই আমি কারও আসল "ক্যালেন্ডার" সারণিতে হস্তক্ষেপ করার সুযোগ নেব না।

--=================================================================================================
--      Simulate just a couple of the necessary columns of the OPs "Calendar" table.
--      This is not a part of the solution.  We're just trying to simulate what the OP has.
--=================================================================================================
--===== Variables to control the dates that will appear in the "Calendar" table.
DECLARE  @StartDT   DATETIME
        ,@EndDT     DATETIME
;
 SELECT  @StartDT = '1900' --Will be inclusive start of this year in calculations.
        ,@EndDT   = '2100' --Will be exclusive start of this year in calculations.
;
--===== Create the "Calendar" table with just enough columns to simulate the OP's.
 CREATE TABLE #datestable
        (
         TheDate    DATETIME NOT NULL
        ,DW         TINYINT  NOT NULL  --SQL standard abbreviate of "Day of Week"
        )
;
--===== Populate the "Calendar" table (uses "Minimal Logging" in 2008+ this case).    
   WITH cteGenDates AS
(
 SELECT TOP (DATEDIFF(dd,@StartDT,@EndDT)) --You can use "DAY" instead of "dd" if you prefer. I don't like it, though.
        TheDate = DATEADD(dd, ROW_NUMBER() OVER (ORDER BY (SELECT NULL))-1, @StartDT)
   FROM      sys.all_columns ac1
  CROSS JOIN sys.all_columns ac2
)
 INSERT INTO #datestable WITH (TABLOCK)
 SELECT  TheDate
        ,DW = DATEDIFF(dd,0,TheDate)%7+1 --Monday is 1, Friday is 5, Sunday is 7 etc.
   FROM cteGenDates
 OPTION (RECOMPILE) -- Help keep "Minimal Logging" in the presence of variables.
;
--===== Add the expected named PK for this example.
  ALTER TABLE #datestable 
    ADD CONSTRAINT PK_datestable PRIMARY KEY CLUSTERED (TheDate)
;

এটিও একটি প্রদত্ত যে আমি জানি না যে ওপি তার "ক্যালেন্ডার" সারণিতে পরিবর্তন করতে পারে কিনা তাই এটি তাকে সাহায্য না করে তবে এটি অন্যকে সাহায্য করতে পারে। এটি মাথায় রেখে, আসুন আমরা একটি ডিডব্লোম (মাসের সপ্তাহের দিন) কলামটি যুক্ত করি। আপনি যদি নামটি পছন্দ না করেন তবে দয়া করে আপনার নিজের বাক্সে যা প্রয়োজন তা এটিকে নির্দ্বিধায় অনুভব করুন।

--===== Add the new column.
  ALTER TABLE #datestable
    ADD DWOM TINYINT NOT NULL DEFAULT (0)
;

এর পরে, আমাদের নতুন কলামটি পপুলেশন করা দরকার। ওপিতে তার আসল অপ্রচলিত পোস্টে এটির একটা ধারণা ছিল।

--===== Populate the new column using the CTE trick for updates so that
     -- we can use a Windowing Function in an UPDATE.
   WITH cteGenDWOM AS
(
 SELECT DW# = ROW_NUMBER() OVER (PARTITION BY DATEDIFF(mm,0,TheDate), DW
                                     ORDER BY TheDate)
        ,DWOM
   FROM #datestable
)
 UPDATE cteGenDWOM
    SET DWOM = DW#
;

এখন, কারণ এটি একটি নির্দিষ্ট দৈর্ঘ্যের কলাম, এটি কেবলমাত্র একগুচ্ছ পৃষ্ঠা বিভাজন তৈরি করেছে যাতে পারফরম্যান্সের জন্য প্রতি পৃষ্ঠায় যতটা সারি থাকে তার জন্য আমাদের ক্লাস্টারড ইনডেক্সটি পুনরায় তৈরি করতে হবে টেবিলটিকে "পুনরায়" মন্তব্য করতে।

--===== "Repack" the Clustered Index to get rid of the page splits we 
     -- caused by adding the new column.
  ALTER INDEX PK_datestable
     ON #datestable
        REBUILD WITH (FILLFACTOR = 100, SORT_IN_TEMPDB = ON)
;

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

--===== Return the 3rd Friday of every month included in the given date range.
 SELECT *
   FROM #datestable
  WHERE TheDate >= '1996-01-01' --I never use "BETWEEN" for dates out of habit for end date offsets.
    AND TheDate <= '2014-08-30'
    AND DW      =  5 --Friday
    AND DWOM    =  3 --The 3rd one for every month
  ORDER BY TheDate
;

0

এখানে একটি সাধারণ কাটা এবং পেস্ট সমাধান রয়েছে। আপনি চাইলে এটিকে একটি ফাংশনে পরিণত করতে পারেন।

Declare @CurrDate Date
Set @CurrDate = '11-20-2016'

declare @first datetime -- First of the month of interest (no time part)
declare @nth tinyint -- Which of them - 1st, 2nd, etc.
declare @dow tinyint -- Day of week we want
set @first = DATEFROMPARTS(YEAR(@CurrDate), MONTH(@CurrDate), 1) 
set @nth = 3
set @dow = 6
declare @result datetime
set @result = @first + 7*(@nth-1)
select  @result + (7 + @dow - datepart(weekday,@result))%7
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.