हाँ, मुझे पता है कि यह पुरानी पोस्ट है। सोचा था कि मैं अपनी उम्र के बावजूद चीजों पर एक अलग तिरछा प्रदान करूंगा। हे ... और मेरी क्षमायाचना। मुझे बस एहसास हुआ कि मैंने लगभग डुप्लिकेट किया है जो @jyao ने पोस्ट किया है।
ओपी के मूल प्रश्न के वर्तमान संपादन के आधार पर, मैं यह पता नहीं लगा सका कि लोग उन उत्तरों को पोस्ट क्यों कर रहे हैं जो उन्होंने किए थे।
संपादन के माध्यम से देखते हुए, मैंने मूल प्रश्न पाया और इसे नीचे पोस्ट किया है ...
मेरे पास एक समय श्रृंखला है जिसमें 1.1.1996 - 30.8.2014 से SQL डेटाबेस जैसे कि तालिका "db.dbo.datestable" है।
मुझे उन तारीखों को निर्धारित करने की आवश्यकता है जो एसक्यूएल में इस तिथि सीमा के लिए "प्रत्येक महीने का तीसरा शुक्रवार" हैं।
मुझे उम्मीद है कि मुझे "रैंक" 3 "सेट करने के लिए" DENSE_RANK () "और" पार्टिशन बाय () "के संयोजन का उपयोग करना चाहिए। हालाँकि, मैं SQL में नया हूँ और सही कोड खोजने में असमर्थ हूँ।
क्या आप इस समस्या को हल कर सकते हैं?
मूल प्रश्न के जिस भाग पर मैंने ज़ोर देकर कहा है, वह कुंजी लगता है। मैं निश्चित रूप से गलत हो सकता है, लेकिन यह मुझे लगता है कि ओपी यह कह रहा था कि उसके पास "कैलेंडर" तालिका है, जिसे "dbo.datestable" कहा जाता है और मेरे लिए, इससे बहुत अधिक अंतर होता है और मुझे अब समझ में आया है कि उत्तर क्यों दिए गए हैं क्या वे शामिल हैं जो तारीखों को उत्पन्न करते हैं क्योंकि यह 10 नवंबर को पोस्ट किया गया था ... सवाल पर अंतिम संपादन के एक दिन बाद, जिसने "dbo.datestable" संदर्भ के अंतिम अवशेषों को हटा दिया।
जैसा मैंने कहा, मैं गलत हो सकता हूं लेकिन यहां मूल प्रश्न की मेरी व्याख्या है।
मेरे पास एक "कैलेंडर" तालिका है, जिसे "dbo.datestable" कहा जाता है। उस तालिका द्वारा कवर की गई तारीखों की किसी भी सीमा को देखते हुए, मैं केवल उन तारीखों को कैसे वापस कर सकता हूं जो उस दी गई तारीख सीमा के भीतर प्रत्येक महीने के 3 वें शुक्रवार हैं?
चूंकि ऐसा करने के लिए पारंपरिक तरीके पहले से ही कवर किए गए हैं, मैं एक विकल्प जोड़ूंगा जो कुछ के लिए सहायक हो सकता है।
चलो उन स्तंभों के एक जोड़े का अनुकरण करें जो मुझे लगता है कि ओपी पहले से ही अपनी तालिका में होगा। बेशक, मैं कॉलम नामों पर अनुमान लगा रहा हूं। आपकी "कैलेंडर" तालिका के लिए जो भी समतुल्य कॉलम हैं, उन्हें उप करें। इसके अलावा, मैं यह सब TempDB में कर रहा हूं, इसलिए मैं किसी के वास्तविक "कैलेंडर" तालिका में हस्तक्षेप करने का मौका नहीं लेता हूं।
--=================================================================================================
-- 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)
;
यह भी एक दिया है कि मुझे नहीं पता कि अगर ओपी अपनी "कैलेंडर" तालिका में बदलाव कर सकता है तो यह उसकी मदद नहीं कर सकता है लेकिन यह दूसरों की मदद कर सकता है। इसे ध्यान में रखते हुए, एक DWoM (सप्ताह के लिए सप्ताह का दिन) कॉलम जोड़ें। यदि आपको नाम पसंद नहीं है, तो कृपया बेझिझक इसे अपने बॉक्स में जो कुछ भी ज़रूरत है उसे बदलने के लिए स्वतंत्र महसूस करें।
--===== 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
;