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

SQLServerで日付の範囲を生成する方法

    この特定の目的のために、以下のクエリは専用のルックアップテーブルを使用するのとほぼ同じくらい効率的であると私は主張します。

    DECLARE @start DATE, @end DATE;
    SELECT @start = '20110714', @end = '20110717';
    
    ;WITH n AS 
    (
      SELECT TOP (DATEDIFF(DAY, @start, @end) + 1) 
        n = ROW_NUMBER() OVER (ORDER BY [object_id])
      FROM sys.all_objects
    )
    SELECT 'Bob', DATEADD(DAY, n-1, @start)
    FROM n;
    

    結果:

    Bob     2011-07-14
    Bob     2011-07-15
    Bob     2011-07-16
    Bob     2011-07-17
    

    おそらく、これは単一のメンバーではなくセットとして必要になるため、この手法を適応させる方法は次のとおりです。

    DECLARE @t TABLE
    (
        Member NVARCHAR(32), 
        RegistrationDate DATE, 
        CheckoutDate DATE
    );
    
    INSERT @t SELECT N'Bob', '20110714', '20110717'
    UNION ALL SELECT N'Sam', '20110712', '20110715'
    UNION ALL SELECT N'Jim', '20110716', '20110719';
    
    ;WITH [range](d,s) AS 
    (
      SELECT DATEDIFF(DAY, MIN(RegistrationDate), MAX(CheckoutDate))+1,
        MIN(RegistrationDate)
        FROM @t -- WHERE ?
    ),
    n(d) AS
    (
      SELECT DATEADD(DAY, n-1, (SELECT MIN(s) FROM [range]))
      FROM (SELECT ROW_NUMBER() OVER (ORDER BY [object_id])
      FROM sys.all_objects) AS s(n)
      WHERE n <= (SELECT MAX(d) FROM [range])
    )
    SELECT t.Member, n.d
    FROM n CROSS JOIN @t AS t
    WHERE n.d BETWEEN t.RegistrationDate AND t.CheckoutDate;
    ----------^^^^^^^ not many cases where I'd advocate between!
    

    結果:

    Member    d
    --------  ----------
    Bob       2011-07-14
    Bob       2011-07-15
    Bob       2011-07-16
    Bob       2011-07-17
    Sam       2011-07-12
    Sam       2011-07-13
    Sam       2011-07-14
    Sam       2011-07-15
    Jim       2011-07-16
    Jim       2011-07-17
    Jim       2011-07-18
    Jim       2011-07-19
    

    @Demsが指摘したように、これは次のように簡略化できます。

    ;WITH natural AS 
    (
      SELECT ROW_NUMBER() OVER (ORDER BY [object_id]) - 1 AS val 
      FROM sys.all_objects
    ) 
    SELECT t.Member, d = DATEADD(DAY, natural.val, t.RegistrationDate) 
      FROM @t AS t INNER JOIN natural 
      ON natural.val <= DATEDIFF(DAY, t.RegistrationDate, t.CheckoutDate);
    


    1. テーブル行の編集GUIを使用してSQLServerテーブルに行を挿入する方法-SQLServer/TSQLチュートリアルパート101

    2. SQLCOALESCE関数の実用的な使用

    3. SQLのみを使用してSQLServer2005の画像フィールドに画像を挿入する

    4. SQLiteのトラップと落とし穴