복붙노트

[SQL] SQL에서 증가 날짜의 결과 세트를 생성

SQL

SQL에서 증가 날짜의 결과 세트를 생성

날짜의 결과 집합을 만들 필요성을 고려한다. 우리는 시작과 끝 날짜를 가지고, 우리는 사이의 날짜의 목록을 생성하고 싶습니다.

DECLARE  @Start datetime
         ,@End  datetime
DECLARE @AllDates table
        (@Date datetime)

SELECT @Start = 'Mar 1 2009', @End = 'Aug 1 2009'

--need to fill @AllDates. Trying to avoid looping. 
-- Surely if a better solution exists.

while 루프와 현재 구현을 고려 :

DECLARE @dCounter datetime
SELECT @dCounter = @Start
WHILE @dCounter <= @End
BEGIN
 INSERT INTO @AllDates VALUES (@dCounter)
 SELECT @dCounter=@dCounter+1 
END

질문 : 당신은 T-SQL을 사용하여 사용자 정의 범위 내에 날짜의 집합을 만들 것인가? SQL 2005 + 가정합니다. 당신의 대답은 SQL 2008 기능을 사용하는 경우, 같은 표시하십시오.

해결법

  1. ==============================

    1.날짜가 더 이상 떨어져 2천47일보다 경우 :

    날짜가 더 이상 떨어져 2천47일보다 경우 :

    declare @dt datetime, @dtEnd datetime
    set @dt = getdate()
    set @dtEnd = dateadd(day, 100, @dt)
    
    select dateadd(day, number, @dt)
    from 
        (select number from master.dbo.spt_values
         where [type] = 'P'
        ) n
    where dateadd(day, number, @dt) < @dtEnd
    

    나는 그렇게 할 몇 가지 요청 후 내 대답을 업데이트했습니다. 왜?

    원래의 대답은 하위 쿼리를 포함

     select distinct number from master.dbo.spt_values
         where name is null
    

    이는 내가 SQL 서버 2008, 2012, 2016 년에 그들을 시험과 동일한 결과를 제공합니다.

    그러나, 나는 spt_values에서 쿼리 할 때 MSSQL 내부적으로, 나는 SELECT 문은 항상 절을 포함하는 것을 발견 코드를 분석하는 시도로 WHERE [유형] = '[마법 코드].

    그러므로 나는 쿼리가 올바른 결과를 반환하지만, 그것은 잘못된 이유에 대한 정확한 결과를 제공하는 것을 결정했다 :

    결과는 간단하게 될 경우에도 [이름]의 값으로 NULL을 가지고 다른 [유형] 값, 0-2047의 외부 범위, 또는 비 연속을 정의하는 SQL Server의 이후 버전이있을 수 있습니다 잘못된.

  2. ==============================

    2.다음은 재귀 CTE (SQL 서버 2005 +)를 사용합니다 :

    다음은 재귀 CTE (SQL 서버 2005 +)를 사용합니다 :

    WITH dates AS (
         SELECT CAST('2009-01-01' AS DATETIME) 'date'
         UNION ALL
         SELECT DATEADD(dd, 1, t.date) 
           FROM dates t
          WHERE DATEADD(dd, 1, t.date) <= '2009-02-01')
    SELECT ...
      FROM TABLE t
      JOIN dates d ON d.date = t.date --etc.
    
  3. ==============================

    3.작업이 방법, 당신이 한 번 테이블 설정을 수행해야합니다

    작업이 방법, 당신이 한 번 테이블 설정을 수행해야합니다

    SELECT TOP 10000 IDENTITY(int,1,1) AS Number
        INTO Numbers
        FROM sys.objects s1
        CROSS JOIN sys.objects s2
    ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)
    

    [숫자 테이블이 설정되면,이 쿼리를 사용합니다 :

    SELECT
        @Start+Number-1
        FROM Numbers
        WHERE Number<=DATEDIFF(day,@Start,@End)+1
    

    캡처로는 수행

    DECLARE  @Start datetime
             ,@End  datetime
    DECLARE @AllDates table
            (Date datetime)
    
    SELECT @Start = 'Mar 1 2009', @End = 'Aug 1 2009'
    
    INSERT INTO @AllDates
            (Date)
        SELECT
            @Start+Number-1
            FROM Numbers
            WHERE Number<=DATEDIFF(day,@Start,@End)+1
    
    SELECT * FROM @AllDates
    

    산출:

    Date
    -----------------------
    2009-03-01 00:00:00.000
    2009-03-02 00:00:00.000
    2009-03-03 00:00:00.000
    2009-03-04 00:00:00.000
    2009-03-05 00:00:00.000
    2009-03-06 00:00:00.000
    2009-03-07 00:00:00.000
    2009-03-08 00:00:00.000
    2009-03-09 00:00:00.000
    2009-03-10 00:00:00.000
    ....
    2009-07-25 00:00:00.000
    2009-07-26 00:00:00.000
    2009-07-27 00:00:00.000
    2009-07-28 00:00:00.000
    2009-07-29 00:00:00.000
    2009-07-30 00:00:00.000
    2009-07-31 00:00:00.000
    2009-08-01 00:00:00.000
    
    (154 row(s) affected)
    
  4. ==============================

    4.@ KM의 대답은 먼저 숫자 테이블을 생성하고, 날짜 범위를 선택하는 데 사용합니다. 임시 번호 테이블없이 동일한 작업을 수행합니다 :

    @ KM의 대답은 먼저 숫자 테이블을 생성하고, 날짜 범위를 선택하는 데 사용합니다. 임시 번호 테이블없이 동일한 작업을 수행합니다 :

    DECLARE  @Start datetime
             ,@End  datetime
    DECLARE @AllDates table
            (Date datetime)
    
    SELECT @Start = 'Mar 1 2009', @End = 'Aug 1 2009';
    
    WITH Nbrs_3( n ) AS ( SELECT 1 UNION SELECT 0 ),
         Nbrs_2( n ) AS ( SELECT 1 FROM Nbrs_3 n1 CROSS JOIN Nbrs_3 n2 ),
         Nbrs_1( n ) AS ( SELECT 1 FROM Nbrs_2 n1 CROSS JOIN Nbrs_2 n2 ),
         Nbrs_0( n ) AS ( SELECT 1 FROM Nbrs_1 n1 CROSS JOIN Nbrs_1 n2 ),
         Nbrs  ( n ) AS ( SELECT 1 FROM Nbrs_0 n1 CROSS JOIN Nbrs_0 n2 )
    
        SELECT @Start+n-1 as Date
            FROM ( SELECT ROW_NUMBER() OVER (ORDER BY n)
                FROM Nbrs ) D ( n )
        WHERE n <= DATEDIFF(day,@Start,@End)+1 ;
    

    자주 이런 일을하는 경우 물론 테스트, 영구 테이블이 아니라 더 확대됨에 될 수있다.

    쿼리는 전술 한 시퀀스 생성을 설명하고 여러 가지 방법을 제공이 문서의 수정 된 버전이다. 나는 그것이 임시 테이블을 생성하지 않는 한이 일을 좋아하고는 sys.objects 테이블의 요소 수에 제한되지 않는다.

  5. ==============================

    5.이 시도. 아니 등 루핑, CTE 제한, 당신은 그냥 아무 대해이 없었다. 기록의 생성. 크로스 조인을 관리하고 필요한 사항에 따라 최고.

    이 시도. 아니 등 루핑, CTE 제한, 당신은 그냥 아무 대해이 없었다. 기록의 생성. 크로스 조인을 관리하고 필요한 사항에 따라 최고.

    select top 100000 dateadd(d,incr,'2010-04-01') as dt from
    (select  incr = row_number() over (order by object_id, column_id), * from
    (
    select a.object_id, a.column_id from  sys.all_columns a cross join sys.all_columns b
    ) as a
    ) as b
    

    중첩 쉽게 제어 및보기로 전환 등을위한주의 사항

  6. ==============================

    6.이 솔루션은 MySQL을위한 동일한 질문의 놀라운 대답을 기반으로합니다. 또한 MSSQL에 매우 성능이 좋은 것입니다. https://stackoverflow.com/a/2157776/466677

    이 솔루션은 MySQL을위한 동일한 질문의 놀라운 대답을 기반으로합니다. 또한 MSSQL에 매우 성능이 좋은 것입니다. https://stackoverflow.com/a/2157776/466677

    select DateGenerator.DateValue from (
      select DATEADD(day, - (a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a)), CONVERT(DATE, GETDATE()) ) as DateValue
      from (select a.a from (values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) as a(a)) as a
      cross join (select b.a from (values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) as b(a)) as b
      cross join (select c.a from (values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) as c(a)) as c
      cross join (select d.a from (values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) as d(a)) as d
    ) DateGenerator
    WHERE DateGenerator.DateValue BETWEEN 'Mar 1 2009' AND 'Aug 1 2009'
    ORDER BY DateGenerator.DateValue ASC
    

    DATEADD 함수에서 미래의 변화 마이너스 기호의 날짜를 들면, 단지 과거 날짜에 대해 작동합니다. 쿼리는 SQL 서버 2008+에서만 작동하지만 노조와 함께 "를 선택 값에서"구조를 대체하여 2005 년에도 다시 작성할 수 있습니다.

  7. ==============================

    7.또 다른 옵션은 .NET에서 기능을 해당 만드는 것입니다. 여기가 보이는 방법은 다음과 같습니다

    또 다른 옵션은 .NET에서 기능을 해당 만드는 것입니다. 여기가 보이는 방법은 다음과 같습니다

    [Microsoft.SqlServer.Server.SqlFunction(
      DataAccess = DataAccessKind.None,
      FillRowMethodName = "fnUtlGetDateRangeInTable_FillRow",
      IsDeterministic = true,
      IsPrecise = true,
      SystemDataAccess = SystemDataAccessKind.None,
      TableDefinition = "d datetime")]
    public static IEnumerable fnUtlGetDateRangeInTable(SqlDateTime startDate, SqlDateTime endDate)
    {
        // Check if arguments are valid
    
        int numdays = Math.Min(endDate.Value.Subtract(startDate.Value).Days,366);
        List<DateTime> res = new List<DateTime>();
        for (int i = 0; i <= numdays; i++)
            res.Add(dtStart.Value.AddDays(i));
    
        return res;
    }
    
    public static void fnUtlGetDateRangeInTable_FillRow(Object row, out SqlDateTime d)
    {
        d = (DateTime)row;
    }
    

    이것은 기본적으로 프로토 타입이며 훨씬 더 똑똑 할 수 있지만, 아이디어를 보여줍니다. 내 경험에서, 작은을위한 적당한 시간 범위에 대한 더 나은 T-SQL에서 구현 된 것보다이 기능을 수행 (몇 년처럼). CLR 버전의 또 다른 멋진 기능은 임시 테이블을 생성하지 않습니다.

  8. ==============================

    8.개요

    개요

    여기 내 버전 (2005 호환)입니다. 이 방법의 장점은 다음과 같습니다

    SQL 바이올린 : http://sqlfiddle.com/#!6/c3896/1

    암호

    소정 파라미터에 기초 번호의 범위를 생성하기위한 재사용 가능한 기능 :

    create function dbo.generate_series
    (
          @start bigint
        , @stop bigint
        , @step bigint = 1
        , @maxResults bigint = 0 --0=unlimitted
    )
    returns @results table(n bigint)
    as
    begin
    
        --avoid infinite loop (i.e. where we're stepping away from stop instead of towards it)
        if @step = 0 return
        if @start > @stop and @step > 0 return
        if @start < @stop and @step < 0 return
    
        --ensure we don't overshoot
        set @stop = @stop - @step
    
        --treat negatives as unlimited
        set @maxResults = case when @maxResults < 0 then 0 else @maxResults end
    
        --generate output
        ;with myCTE (n,i) as 
        (
            --start at the beginning
            select @start
            , 1
            union all
            --increment in steps
            select n + @step
            , i + 1
            from myCTE 
            --ensure we've not overshot (accounting for direction of step)
            where (@maxResults=0 or i<@maxResults)
            and 
            (
                   (@step > 0 and n <= @stop)
                or (@step < 0 and n >= @stop)
            )  
        )
        insert @results
        select n 
        from myCTE
        option (maxrecursion 0) --sadly we can't use a variable for this; however checks above should mean that we have a finite number of recursions / @maxResults gives users the ability to manually limit this 
    
        --all good  
        return
    
    end
    

    시나리오에 대한 사용이 퍼팅 :

    declare @start datetime = '2013-12-05 09:00'
           ,@end  datetime = '2014-03-02 13:00'
    
    --get dates (midnight)
    --, rounding <12:00 down to 00:00 same day, >=12:00 to 00:00 next day
    --, incrementing by 1 day
    select CAST(n as datetime)
    from dbo.generate_series(cast(@start as bigint), cast(@end as bigint), default, default)
    
    --get dates (start time)
    --, incrementing by 1 day
    select CAST(n/24.0 as datetime)
    from dbo.generate_series(cast(@start as float)*24, cast(@end as float)*24, 24, default)
    
    --get dates (start time)
    --, incrementing by 1 hour
    select CAST(n/24.0 as datetime)
    from dbo.generate_series(cast(@start as float)*24, cast(@end as float)*24, default, default)
    

    호환 2005

  9. ==============================

    9.CTE 같은 나는 그것을 쉽게 읽고 유지하는 것에 따라

    CTE 같은 나는 그것을 쉽게 읽고 유지하는 것에 따라

    Declare @mod_date_from date =getdate();
    Declare @mod_date_to date =dateadd(year,1,@mod_date_from);
    
    with cte_Dates as (
                SELECT @mod_date_from as reqDate
                UNION ALL
                SELECT DATEADD(DAY,1,reqDate)
                FROM cte_Dates
                WHERE DATEADD(DAY,1,reqDate) < @mod_date_to
            )
            SELECT * FROM cte_Dates
            OPTION(MAXRECURSION 0);
    

    세트 MAXRECURSION을 잊지 마세요

  10. ==============================

    10.당신의 두 날짜 사이의 차이는 0의 정수와 임시 테이블을 만들 수 있습니다.

    당신의 두 날짜 사이의 차이는 0의 정수와 임시 테이블을 만들 수 있습니다.

    SELECT DATE_ADD(@Start, INTERVAL tmp_int DAY) AS the_date FROM int_table;
    
  11. ==============================

    11.나는 다음을 사용 :

    나는 다음을 사용 :

    SELECT * FROM dbo.RangeDate(GETDATE(), DATEADD(d, 365, GETDATE()));
    
    -- Generate a range of up to 65,536 contiguous DATES
    CREATE FUNCTION dbo.RangeDate (   
        @date1 DATE = NULL
      , @date2 DATE = NULL
    )   
    RETURNS TABLE   
    AS   
    RETURN (
        SELECT D = DATEADD(d, A.N, CASE WHEN @date1 <= @date2 THEN @date1 ELSE @date2 END)
        FROM dbo.RangeSmallInt(0, ABS(DATEDIFF(d, @date1, @date2))) A
    );
    
    -- Generate a range of up to 65,536 contiguous BIGINTS
    CREATE FUNCTION dbo.RangeSmallInt (
        @num1 BIGINT = NULL
      , @num2 BIGINT = NULL
    )
    RETURNS TABLE
    AS
    RETURN (
        WITH Numbers(N) AS (
            SELECT N FROM(VALUES
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 16
              , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 32
              , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 48
              , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 64
              , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 80
              , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 96
              , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 112
              , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 128
              , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 144
              , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 160
              , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 176
              , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 192
              , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 208
              , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 224
              , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 240
              , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 256
            ) V (N)
        )    
        SELECT TOP (
                   CASE
                       WHEN @num1 IS NOT NULL AND @num2 IS NOT NULL THEN ABS(@num1 - @num2) + 1
                       ELSE 0
                   END
               )
               ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) + CASE WHEN @num1 <= @num2 THEN @num1 ELSE @num2 END - 1
        FROM Numbers A
           , Numbers B
        WHERE ABS(@num1 - @num2) + 1 < 65537
    );
    

    그것은 모든 이미 제안 된 솔루션의 다양한에서 서로 다른 것이 아니라 그것에 대해 같은 몇 가지 내가있다 :

  12. ==============================

    12.이 사람은 작동합니다.

    이 사람은 작동합니다.

    sysobjects의 상위에서 1,000 DATEADD (d 이드 BY, ROW_NUMBER () OVER (ORDER) GETDATE ()을) 선택할

  13. ==============================

    13.내가 권하고 싶습니다 무엇 : 숫자의 보조 테이블을 만들고 날짜의 목록을 생성하는 데 사용합니다. 또한 재귀 CTE를 사용할 수 있지만, 그 숫자의 보조 테이블에 합류뿐만 아니라 수행 할 수 있습니다. 참조 SQL, 두 옵션에 대한 정보를 숫자의 보조 테이블.

    내가 권하고 싶습니다 무엇 : 숫자의 보조 테이블을 만들고 날짜의 목록을 생성하는 데 사용합니다. 또한 재귀 CTE를 사용할 수 있지만, 그 숫자의 보조 테이블에 합류뿐만 아니라 수행 할 수 있습니다. 참조 SQL, 두 옵션에 대한 정보를 숫자의 보조 테이블.

  14. ==============================

    14.정말 (+1) 이상 KM의 솔루션과 같은, 당신의 "더 루프"가정에 의문을 제기하지되어야하지만 - 앱이 작동 할 것이라는 그럴듯한 날짜 범위 주어진 루프를 갖는 것은 정말 그렇게 비싼해서는 안됩니다. 주요 트릭은 쿼리의 매우 큰 세트를 다시 계산 똑같은 날짜로 시스템 속도가 느려지지 않도록하는 것이, 준비 / 캐시 테이블에서 루프의 결과를 strore하는 것입니다. 예를 들면 각 쿼리 만 계산하여 / 캐시 캐시에 그것을 필요로 이미되지 않습니다 (및 범위는 응용 프로그램의 비즈니스 요구에 의해 결정으로-미리 채울 사전에 몇 가지 현실적인 날짜 범위로 2 ~ 같은 년을 표를) 날짜 범위.

    정말 (+1) 이상 KM의 솔루션과 같은, 당신의 "더 루프"가정에 의문을 제기하지되어야하지만 - 앱이 작동 할 것이라는 그럴듯한 날짜 범위 주어진 루프를 갖는 것은 정말 그렇게 비싼해서는 안됩니다. 주요 트릭은 쿼리의 매우 큰 세트를 다시 계산 똑같은 날짜로 시스템 속도가 느려지지 않도록하는 것이, 준비 / 캐시 테이블에서 루프의 결과를 strore하는 것입니다. 예를 들면 각 쿼리 만 계산하여 / 캐시 캐시에 그것을 필요로 이미되지 않습니다 (및 범위는 응용 프로그램의 비즈니스 요구에 의해 결정으로-미리 채울 사전에 몇 가지 현실적인 날짜 범위로 2 ~ 같은 년을 표를) 날짜 범위.

  15. ==============================

    15.가장 좋은 대답은 CTE를 사용하는 것이 아마도,하지만 당신은 그것을 사용할 수 있습니다 보장은 없습니다. 내 경우, 나는 CTE이나 저장 프로 시저를 사용하지 못했습니다 ... 쿼리 생성기에 의해 dinamically 만든 기존 쿼리 내에서이 목록을 삽입했다.

    가장 좋은 대답은 CTE를 사용하는 것이 아마도,하지만 당신은 그것을 사용할 수 있습니다 보장은 없습니다. 내 경우, 나는 CTE이나 저장 프로 시저를 사용하지 못했습니다 ... 쿼리 생성기에 의해 dinamically 만든 기존 쿼리 내에서이 목록을 삽입했다.

    그래서, Devio의 대답은 정말 유용했다,하지만 난 내 환경에서 작동하도록 수정했다.

    마스터 DB에 액세스 할 수없는 경우, 당신은 당신의 데이터베이스에 다른 테이블을 사용할 수있다. 이전의 예에 대해, 최대 기간은 선택이 끝난 테이블 내부 행의 수에 의해 주어진다.

    힘든 내 예에서 ROW_NUMBER를 사용하여, 당신은 실제 INT 컬럼없이 테이블을 사용할 수 있습니다.

    declare @bd datetime --begin date
    declare @ed datetime --end date
    
    set @bd = GETDATE()-50
    set @ed = GETDATE()+5
    
    select 
    DATEADD(dd, 0, DATEDIFF(dd, 0, Data)) --date format without time
    from 
    (
        select 
        (GETDATE()- DATEDIFF(dd,@bd,GETDATE())) --Filter on the begin date
        -1 + ROW_NUMBER() over (ORDER BY [here_a_field]) AS Data 
        from [Table_With_Lot_Of_Rows]
    ) a 
    where Data < (@ed + 1) --filter on the end date
    
  16. ==============================

    16.정말 내가 필요 SQL 서버 2000 (그래서 CTE를 사용할 수 없습니다) 그러나 실행하는 것이이 같은 정확히 뭔가를 필요에 따라 Devio의 솔루션처럼,이 수정 될 수있는 방법 만 날짜를 생성하는 요일의 특정 세트에 맞 춥니 다. 예를 들면, 나는 단지 내가 다음 수를 계획에 따라 선택할 특히 어떤 순서 월요일, 수요일, 금요일 또는에 맞춰 가을 날짜를 원하는 :

    정말 내가 필요 SQL 서버 2000 (그래서 CTE를 사용할 수 없습니다) 그러나 실행하는 것이이 같은 정확히 뭔가를 필요에 따라 Devio의 솔루션처럼,이 수정 될 수있는 방법 만 날짜를 생성하는 요일의 특정 세트에 맞 춥니 다. 예를 들면, 나는 단지 내가 다음 수를 계획에 따라 선택할 특히 어떤 순서 월요일, 수요일, 금요일 또는에 맞춰 가을 날짜를 원하는 :

    Sunday = 1
    Monday = 2
    Tuesday = 3
    Wednesday = 4
    Thursday = 5
    Friday = 6
    Saturday = 7
    

    예:

    StartDate = '2015-04-22' EndDate = '2017-04-22' --2 years worth
    Filter on: 2,4,6 --Monday, Wednesday, Friday dates only
    

    내가 코드에 노력하고있어 두 개의 추가 필드를 추가하는 것입니다 : 하루, day_code 그런 조건으로 생성 된 목록을 필터링 ...

    나는 다음과 함께했다 :

    declare @dt datetime, @dtEnd datetime
    set @dt = getdate()
    set @dtEnd = dateadd(day, 1095, @dt)
    
    select dateadd(day, number, @dt) as Date, DATENAME(DW, dateadd(day, number, @dt)) as Day_Name into #generated_dates
    from 
        (select distinct number from master.dbo.spt_values
         where name is null
        ) n
    where dateadd(day, number, @dt) < @dtEnd 
    
    select * from #generated_dates where Day_Name in ('Saturday', 'Friday')
    
    drop table #generated_dates
    
  17. ==============================

    17.이 10,000 일에 대한 날짜 목록을 생성합니다 (이십칠년가 틱)

    이 10,000 일에 대한 날짜 목록을 생성합니다 (이십칠년가 틱)

    declare @startDateTime datetime = '2000-06-02 00:00:00';
    declare @endDateTime datetime = '2028-06-02 23:59:59';
    
    
    SELECT DATEADD(DAY, (Thousands+Hundreds+Tens+Units) , @startDateTime) D
    FROM ( 
                  SELECT 0 Thousands
                  UNION ALL SELECT 1000 UNION ALL SELECT 2000 UNION ALL SELECT 3000
                  UNION ALL SELECT 4000 UNION ALL SELECT 5000 UNION ALL SELECT 6000
                  UNION ALL SELECT 7000 UNION ALL SELECT 8000 UNION ALL SELECT 9000
           ) Thousands
           CROSS JOIN ( 
                  SELECT 0 Hundreds
                  UNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300
                  UNION ALL SELECT 400 UNION ALL SELECT 500 UNION ALL SELECT 600
                  UNION ALL SELECT 700 UNION ALL SELECT 800 UNION ALL SELECT 900
           ) Hundreds
           CROSS JOIN ( 
                  SELECT 0 Tens
                  UNION ALL SELECT  10 UNION ALL SELECT  20 UNION ALL SELECT  30
                  UNION ALL SELECT  40 UNION ALL SELECT  50 UNION ALL SELECT  60
                  UNION ALL SELECT  70 UNION ALL SELECT  80 UNION ALL SELECT  90
           ) Tens 
           CROSS JOIN ( 
                  SELECT 0 Units
                  UNION ALL SELECT   1 UNION ALL SELECT   2 UNION ALL SELECT   3
                  UNION ALL SELECT   4 UNION ALL SELECT   5 UNION ALL SELECT   6
                  UNION ALL SELECT   7 UNION ALL SELECT   8 UNION ALL SELECT   9
           ) Units
    WHERE
           DATEADD(DAY, (Thousands+Hundreds+Tens+Units), @startDateTime)  <= @endDateTime 
    ORDER BY (Thousands+Hundreds+Tens+Units)
    
  18. from https://stackoverflow.com/questions/1478951/generate-a-resultset-of-incrementing-dates-in-tsql by cc-by-sa and MIT license