sql >> データベース >  >> RDS >> Sqlserver

SQL は、当会計年度の銀行休業日を差し引いた 1 か月あたりの合計稼働日を入力します。

    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 の代わりに 休日テーブルからレコードを削除します。 SQL Server では、LEFT JOIN/IS NULL は NOT EXISTS よりも効率的ではありません
  6. これらはすべて些細なことですが、他の誰かの質問をレビューするときに(少なくとも頭の中で)批判するものなので、自分の仕事を本当に修正することはできません!クエリを書き直すと、

    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. Wordpressユーザーとusermeta-1つのテーブルの複数の行を別のテーブルの1つの行に結合する

    2. PostgreSQL-1時間以上前のデータを削除してから、同じテーブルに新しいデータを挿入する

    3. 2つの異なるデータベースからの2つの類似したクエリの結果を組み合わせたテーブルをエコーするにはどうすればよいですか?

    4. 列名の前のアットマークSQLステートメント