तालिका के साथ BETWEEN का उपयोग करने के तरीके के साथ आना जैसा कि यह काम करेगा, लेकिन हर मामले में खराब प्रदर्शन होगा:
- यह तारीखों के रूप में काम करने के बजाय पंक्तियों पर किसी प्रकार की गणना करने के लिए अधिक CPU की खपत करेगा।
- यह तालिका में प्रत्येक पंक्ति पर एक टेबल स्कैन को सबसे खराब स्थिति में मजबूर करेगा, लेकिन यदि आपके कॉलम में इंडेक्स हैं, तो सही क्वेरी के साथ एक खोज संभव है। यह एक बड़ा प्रदर्शन अंतर हो सकता है, क्योंकि बाधाओं को BETWEEN क्लॉज में बाध्य करने से इंडेक्स का उपयोग करना अक्षम हो जाएगा।
यदि आपके पास अपने दिनांक कॉलम पर एक अनुक्रमणिका है और प्रदर्शन के बारे में बिल्कुल भी परवाह है, तो मैं इसके बजाय निम्नलिखित का सुझाव देता हूं:
DECLARE
@FromDate date = '20111101',
@ToDate date = '20120201';
SELECT *
FROM dbo.YourTable T
WHERE
(
T.[Year] > Year(@FromDate)
OR (
T.[Year] = Year(@FromDate)
AND T.[Month] >= Month(@FromDate)
)
) AND (
T.[Year] < Year(@ToDate)
OR (
T.[Year] = Year(@ToDate)
AND T.[Month] <= Month(@ToDate)
)
);
हालांकि, यह समझ में आता है कि आप इस तरह के निर्माण का उपयोग नहीं करना चाहते क्योंकि यह बहुत अजीब है। तो यहां एक समझौता क्वेरी है, जो कम से कम संख्यात्मक गणना का उपयोग करती है और डेट-टू-स्ट्रिंग-रूपांतरण गणना से कम CPU का उपयोग करेगी (हालांकि मजबूर स्कैन के लिए पर्याप्त कम नहीं है जो वास्तविक प्रदर्शन समस्या है)।
SELECT *
FROM dbo.YourTable T
WHERE
T.[Year] * 100 + T.[Month] BETWEEN 201111 AND 201202;
यदि आपके पास Year
. पर एक अनुक्रमणिका है , आप निम्न प्रकार से क्वेरी सबमिट करके एक बड़ा बढ़ावा प्राप्त कर सकते हैं, जिसे तलाशने का अवसर मिलता है:
SELECT *
FROM dbo.YourTable T
WHERE
T.[Year] * 100 + T.[Month] BETWEEN 201111 AND 201202
AND T.[Year] BETWEEN 2011 AND 2012; -- allows use of an index on [Year]
हालांकि यह एक BETWEEN
. का उपयोग करने की आपकी आवश्यकता को तोड़ता है अभिव्यक्ति, यह बहुत अधिक दर्दनाक नहीं है और Year
. के साथ बहुत अच्छा प्रदर्शन करेगा सूचकांक।
आप अपनी टेबल भी बदल सकते हैं। स्पष्ट रूप से, दिनांक डेटा प्रकार वाले एकल कॉलम के बजाय अपने दिनांक भागों के लिए अलग-अलग संख्याओं का उपयोग करना अच्छा नहीं है। इसके ठीक न होने का कारण यह है कि आप अभी जिस सटीक समस्या का सामना कर रहे हैं--इससे पूछताछ करना बहुत कठिन है।
कुछ डेटा वेयरहाउसिंग परिदृश्यों में जहां बाइट्स को सहेजना बहुत मायने रखता है, मैं उन स्थितियों की कल्पना कर सकता हूं जहां आप तारीख को एक संख्या के रूप में संग्रहीत कर सकते हैं (जैसे 201111
) लेकिन इसकी अनुशंसा नहीं की जाती है। सर्वश्रेष्ठ समाधान महीने और वर्ष के संख्यात्मक मान को विभाजित करने के बजाय तिथियों का उपयोग करने के लिए अपनी तालिका को बदलना है। बस महीने के पहले दिन को स्टोर करें, यह पहचानते हुए कि यह पूरे महीने के लिए है।
यदि आप इन स्तंभों का उपयोग करने के तरीके को बदलना एक विकल्प नहीं है, लेकिन फिर भी आप अपनी तालिका बदल सकते हैं, तो आप एक स्थायी गणना कॉलम जोड़ सकते हैं:
ALTER Table dbo.YourTable
ADD ActualDate AS (DateAdd(year, [Year] - 1900, DateAdd(month, [Month], '18991201')))
PERSISTED;
इसके साथ आप बस यह कर सकते हैं:
SELECT *
FROM dbo.YourTable
WHERE
ActualDate BETWEEN '20111101' AND '20120201';
PERSISTED
कीवर्ड का अर्थ है कि जब आप अभी भी एक स्कैन प्राप्त करेंगे, तो उसे प्रत्येक पंक्ति पर कोई गणना नहीं करनी पड़ेगी क्योंकि अभिव्यक्ति की गणना प्रत्येक INSERT या UPDATE पर की जाती है और पंक्ति में संग्रहीत होती है। लेकिन आप कर सकते हैं यदि आप इस कॉलम पर एक इंडेक्स जोड़ते हैं, तो एक खोज प्राप्त करें, जो इसे बहुत अच्छा प्रदर्शन करेगा (हालांकि कुल मिलाकर, यह अभी भी वास्तविक दिनांक कॉलम का उपयोग करने के लिए बदलने के रूप में आदर्श नहीं है, क्योंकि यह अधिक स्थान लेगा और INSERTs को प्रभावित करेगा और अद्यतन):
CREATE NONCLUSTERED INDEX IX_YourTable_ActualDate ON dbo.YourTable (ActualDate);
सारांश:यदि आप वास्तव में तालिका को किसी भी तरह से नहीं बदल सकते हैं, तो आपको किसी तरह से समझौता करना होगा। जब आपकी तिथियों को अलग-अलग कॉलम में विभाजित करके संग्रहीत किया जाता है, तो आप चाहते हैं कि सरल सिंटैक्स प्राप्त करना संभव नहीं होगा, जो अच्छा प्रदर्शन करेगा।