Sqlserver
 sql >> डेटाबेस >  >> RDS >> Sqlserver

SQL प्रति माह कुल कार्य दिवसों को चालू वित्तीय वर्ष के लिए बैंक अवकाश घटा देता है

DECLARE @StartDate DATETIME, @EndDate DATETIME

SELECT  @StartDate = '01/04/2011',
        @EndDate = '31/03/2012'
        
CREATE TABLE #Data (FirstDay DATETIME NOT NULL PRIMARY KEY, WorkingDays INT NOT NULL)

;WITH DaysCTE ([Date]) AS
(   SELECT  @StartDate
    UNION ALL
    SELECT  DATEADD(DAY, 1, [Date])
    FROM    DaysCTE
    WHERE   [Date] <= @Enddate
)

INSERT INTO #Data
SELECT  MIN([Date]),
        COUNT(*) [Day]
FROM    DaysCTE
        LEFT JOIN HolidayTable
            ON [Date] BETWEEN HolStart AND HolEnd
WHERE   HolidayTypeID IS NULL
AND     DATENAME(WEEKDAY, [Date]) NOT IN ('Saturday', 'Sunday')
GROUP BY DATEPART(MONTH, [Date]), DATEPART(YEAR, [Date])
OPTION (MAXRECURSION 366)

DECLARE @Date DATETIME
SET @Date = (SELECT MIN(FirstDay) FROM #Data)

SELECT  Period,
        WorkingDays [Days Available (Minus the Holidays)]
FROM    (   SELECT  DATENAME(MONTH, Firstday) [Period],
                    WorkingDays,
                    0 [SortField],
                    FirstDay
            FROM    #Data
            UNION
            SELECT  DATENAME(MONTH, @Date) + ' - ' + DATENAME(MONTH, Firstday),
                    (   SELECT  SUM(WorkingDays)
                        FROM    #Data b
                        WHERE   b.FirstDay <= a.FirstDay
                    ) [WorkingDays],
                    1 [SortField],
                    FirstDay 
            FROM    #Data a
            WHERE   FirstDay > @Date
        ) data
ORDER BY SortField, FirstDay

DROP TABLE #Data

यदि आप 1 वर्ष से अधिक समय तक ऐसा करते हैं तो आपको लाइन बदलनी होगी:

OPTION (MAXRECURSION 366)

अन्यथा आपको एक त्रुटि मिलेगी - यह संख्या आपके द्वारा क्वेरी किए जा रहे दिनों की संख्या से अधिक होनी चाहिए।

संपादित करें

मैं अभी-अभी अपने इस पुराने उत्तर पर आया हूं और वास्तव में इसे पसंद नहीं करता, ऐसी बहुत सी चीजें हैं जिन्हें मैं अब बुरा अभ्यास मानता हूं, इसलिए मैं सभी मुद्दों को ठीक करने जा रहा हूं:

  1. मैंने इनके साथ बयानों को समाप्त नहीं किया एक अर्ध कोलन ठीक से
  2. तिथियों की सूची बनाने के लिए पुनरावर्ती CTE का उपयोग किया
  3. सम्मिलित करने के लिए कॉलम सूची को शामिल नहीं किया
  4. सप्ताहांत को समाप्त करने के लिए DATENAME का उपयोग किया, जो कि भाषा विशिष्ट है, स्पष्ट रूप से सेट करने के लिए बेहतर है DATEFIRST और DATEPART . का उपयोग करें
  5. इस्तेमाल किया गया LEFT JOIN/IS NULL के बजाय NOT EXISTS हॉलिडे टेबल से रिकॉर्ड खत्म करने के लिए। एसक्यूएल सर्वर में LEFT JOIN/IS NULL NOT EXISTS से कम कुशल है

ये सभी छोटी चीजें हैं, लेकिन वे ऐसी चीजें हैं जिनकी मैं किसी और की क्वेरी की समीक्षा करते समय (कम से कम मेरे दिमाग में अगर ज़ोर से नहीं तो) आलोचना करूँगा, इसलिए वास्तव में मैं अपने काम को सही नहीं कर सकता! क्वेरी को फिर से लिखना देना होगा।

SET DATEFIRST 1;

DECLARE @StartDate DATETIME = '20110401',
        @EndDate DATETIME = '20120331';

CREATE TABLE #Data (FirstDay DATETIME NOT NULL PRIMARY KEY, WorkingDays INT NOT NULL);

WITH DaysCTE ([Date]) AS
(   SELECT  TOP (DATEDIFF(DAY, @StartDate, @EndDate) + 1)
            DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @StartDate)
    FROM    sys.all_objects a
)
INSERT INTO #Data (FirstDay, WorkingDays)
SELECT  FirstDay =  MIN([Date]),
        WorkingDays = COUNT(*) 
FROM    DaysCTE d
WHERE   DATEPART(WEEKDAY, [Date]) NOT IN (6, 7)
AND     NOT EXISTS
        (   SELECT  1
            FROM    dbo.HolidayTable ht
            WHERE   d.[Date] BETWEEN ht.HolStart AND ht.HolEnd
        )
GROUP BY DATEPART(MONTH, [Date]), DATEPART(YEAR, [Date]);

DECLARE @Date DATETIME = (SELECT MIN(FirstDay) FROM #Data);

SELECT  Period,
        [Days Available (Minus the Holidays)] = WorkingDays 
FROM    (   SELECT  DATENAME(MONTH, Firstday) [Period],
                    WorkingDays,
                    0 [SortField],
                    FirstDay
            FROM    #Data
            UNION
            SELECT  DATENAME(MONTH, @Date) + ' - ' + DATENAME(MONTH, Firstday),
                    (   SELECT  SUM(WorkingDays)
                        FROM    #Data b
                        WHERE   b.FirstDay <= a.FirstDay
                    ) [WorkingDays],
                    1 [SortField],
                    FirstDay 
            FROM    #Data a
            WHERE   FirstDay > @Date
        ) data
ORDER BY SortField, FirstDay;

DROP TABLE #Data;

अंतिम बिंदु के रूप में, यह क्वेरी कैलेंडर तालिका जो सभी तिथियों को संग्रहीत करता है, और छुट्टियों को संग्रहीत करने वाली अवकाश तालिका का उपयोग करने के बजाय कार्य दिवसों, छुट्टियों आदि के लिए झंडे रखता है।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. समय-आधारित डेटा के लिए विभिन्न दृष्टिकोणों का प्रदर्शन

  2. SQL सर्वर 2008 में कुल टेबलस्पेस उपयोग कैसे प्राप्त करें?

  3. SQL सर्वर में 1:1 और 1:m संबंधों को डिज़ाइन करना

  4. SQL सर्वर nvarchar स्ट्रिंग्स के अंदर खोज करते समय उच्च CPU का उपयोग करता है

  5. SQL सर्वर में एक विशाल तालिका डेटा को किसी अन्य तालिका में कैसे कॉपी करें