복붙노트

[SQL] 어떻게 2000 SQL 서버의 날짜 가득 임시 테이블을 생성 할 수 있습니까?

SQL

어떻게 2000 SQL 서버의 날짜 가득 임시 테이블을 생성 할 수 있습니까?

나는 날짜의 범위를 보유하고 임시 테이블뿐만 아니라 열 몇을 만들 필요가 미래의 사용을 위해 보류 자리 값 (0). 내가 필요로하는 날짜는 이러한 변수가 떨어져 몇 년이 될 수 $의 startDate와 endDate가 $ 사이에 매월 1 일입니다.

내 원래의 SQL 문은 다음과 같이 보았다 :

select dbo.FirstOfMonth(InsertDate) as Month, 0 as Trials, 0 as Sales
into #dates
from customer
group by dbo.FirstOfMonth(InsertDate)

"FirstOfMonth"나는 꽤 많은 정확히 자정에 시간이 제공된 날짜 월의 첫 날을 돌려 말하는 않는 만든 사용자 정의 함수입니다.

이것은 내가 몇 달 날짜 삽입 레코드가 없었다 있었다 있었다 어디에 내 날짜의 간격이 가끔 있었다 발견 할 때까지 내가 필요로 무엇을 거의 정확하게 생산했다. 내 결과가 여전히 누락 개월이해야하기 때문에 나는 다른 접근 방식이 필요합니다.

내가 필요로하는 날짜의 범위의 필요성을 기대 저장 프로 시저에 다음 선언을 추가 한 ...

declare $startDate set $startDate = select min(InsertDate) from customer
declare $endDate set $endDate = select max(InsertDate) from customer

...하지만 난 여기에 무엇을 할 수 있는지 모르겠어요.

나는 (내가 SQL 자주 일을하지 않고 나는 그것이 SQL 서버의 이전 버전에 경향 수행 할 때)이 질문이 질문하지만, 솔직히, 그 대답은 내 머리 이상과 유사 알고 몇 가지 사소한있다 저를 던지고있다 차이.

해결법

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

    1.이 빨리 날짜 170 년 가치가있는 테이블을 채 웁니다.

    이 빨리 날짜 170 년 가치가있는 테이블을 채 웁니다.

    CREATE TABLE CalendarMonths (
      date DATETIME,
      PRIMARY KEY (date)
    )
    
    DECLARE
      @basedate DATETIME,
      @offset   INT
    SELECT
      @basedate = '01 Jan 2000',
      @offset = 1
    
    WHILE (@offset < 2048)
    BEGIN
      INSERT INTO CalendarMonths SELECT DATEADD(MONTH, @offset, date) FROM CalendarMonths
      SELECT @offset = @offset + @offset
    END
    

    그런 다음 필요한 날짜의 범위, 해당 테이블에 합류 LEFT로 사용할 수 있습니다.

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

    2.나는 비슷한 필요하지만, 모든 일 대신 모든 개월.

    나는 비슷한 필요하지만, 모든 일 대신 모든 개월.

    여기 2000-01-01에서 2099년 12월 31일 모든 날짜와 영구 테이블을 생성하는 SQL이야, 시작 지점으로 MatBailie의 코드를 사용하여 :

    CREATE TABLE _Dates (
      d DATE,
      PRIMARY KEY (d)
    )
    DECLARE @dIncr DATE = '2000-01-01'
    DECLARE @dEnd DATE = '2100-01-01'
    
    WHILE ( @dIncr < @dEnd )
    BEGIN
      INSERT INTO _Dates (d) VALUES( @dIncr )
      SELECT @dIncr = DATEADD(DAY, 1, @dIncr )
    END
    
  3. ==============================

    3.아마 일정 테이블을 사용합니다. 데이터베이스에 영구 테이블을 만들고 모든 날짜로 채 웁니다. 당신이 100 년의 범위를 포함하더라도, 테이블은 여전히 ​​~ 거기에 36,525 행을 가질 것이다.

    아마 일정 테이블을 사용합니다. 데이터베이스에 영구 테이블을 만들고 모든 날짜로 채 웁니다. 당신이 100 년의 범위를 포함하더라도, 테이블은 여전히 ​​~ 거기에 36,525 행을 가질 것이다.

    CREATE TABLE dbo.Calendar (
        calendar_date    DATETIME    NOT NULL,
        is_weekend       BIT         NOT NULL,
        is_holiday       BIT         NOT NULL,
        CONSTRAINT PK_Calendar PRIMARY KEY CLUSTERED (calendar_date)
    )
    

    테이블이 작성되면, 바로 그것이 당신에게 항상 거기하고 사용할 수 그래서, 루프에서 한 번을 채 웁니다.

    귀하의 질의 사항은 다음과 같이 될 수있다 :

    SELECT
        C.calendar_date,
        0 AS trials,
        0 AS sales
    FROM
        dbo.Calendar C
    WHERE
        C.calendar_date BETWEEN @start_date AND @end_date AND
        DAY(C.calendar_date) = 1
    

    당신이 필요하지만 당신은 고객 테이블에 가입 할 수 있습니다에, 만약 당신이 원하는 FirstOfMonth (InsertDate) = C.calendar_date에 합류 외부.

    당신은 DAY () 함수를 호출의 오버 헤드를 피할 것이다하려는 경우에도 DAY_OF_MONTH에 대한 열을 포함 할 수 있지만, 아마 문제가 어떤 식 으로든를하지 않도록 즉, 매우 사소한입니다.

  4. ==============================

    4.영구 테이블을 생성하지 않으려는 경우 물론 이것은 SQL-서버 2000에 있지만 현대 데이터베이스에서 작동하지 않습니다. 당신이 남아있는 데이터는이 시도에 가입 할 수 있도록하는 대신 테이블을 작성할 테이블 변수를 사용할 수 있습니다. 증가 유형을 변경 HOUR 등의 날을 변경합니다.

    영구 테이블을 생성하지 않으려는 경우 물론 이것은 SQL-서버 2000에 있지만 현대 데이터베이스에서 작동하지 않습니다. 당신이 남아있는 데이터는이 시도에 가입 할 수 있도록하는 대신 테이블을 작성할 테이블 변수를 사용할 수 있습니다. 증가 유형을 변경 HOUR 등의 날을 변경합니다.

    declare @CalendarMonths table (date DATETIME,  PRIMARY KEY (date)
    )
    
    DECLARE
      @basedate DATETIME,
      @offset   INT
    SELECT
      @basedate = '01 Jan 2014',
      @offset = 1
      INSERT INTO @CalendarMonths SELECT @basedate
    
    WHILE ( DATEADD(DAY, @offset, @basedate) < CURRENT_TIMESTAMP)
    BEGIN
      INSERT INTO @CalendarMonths SELECT DATEADD(HOUR, @offset, date) FROM @CalendarMonths where DATEADD(DAY, @offset, date) < CURRENT_TIMESTAMP
      SELECT @offset = @offset + @offset
    END
    
  5. ==============================

    5.유용한 kludge의 출발점 날짜 범위 또는 특정 목록을 지정합니다 :

    유용한 kludge의 출발점 날짜 범위 또는 특정 목록을 지정합니다 :

    SELECT *
    FROM 
        (SELECT CONVERT(DateTime,'2017-1-1')+number AS [Date]
         FROM master..spt_values WHERE type='P' AND number<370) AS DatesList
    WHERE DatesList.Date IN ('2017-1-1','2017-4-14','2017-4-17','2017-12-25','2017-12-26')
    

    유형 = 'P'는, 그래서 다섯의 그 WHERE 및 날짜의 반 년의 가치는 당신이 그것을 필요로하는 경우에 당신은 master..spt_values에서 2047에 0을 얻을 수 있습니다!

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

    6.아래 테스트하고 뒤얽힌 조금 비록 그것은 작동합니다.

    아래 테스트하고 뒤얽힌 조금 비록 그것은 작동합니다.

    나는 시험의 날짜에 임의의 값을 할당.

    DECLARE @SD smalldatetime,
            @ED smalldatetime,
            @FD smalldatetime,
            @LD smalldatetime,
            @Mct int,
            @currct int = 0
    
    SET @SD = '1/15/2011'
    SET @ED = '2/02/2012'
    
    
    SET @FD = (DATEADD(dd, -1*(Datepart(dd, @SD)-1), @sd))
    SET @LD = (DATEADD(dd, -1*(Datepart(dd, @ED)-1), @ED))
    
    SET @Mct = DATEDIFF(mm, @FD, @LD)
    
    CREATE TABLE #MyTempTable (FoM smalldatetime, Trials int, Sales money)
    
    WHILE @currct <= @Mct
    BEGIN
        INSERT INTO #MyTempTable (FoM, Trials, Sales)
        VALUES
        (DATEADD(MM, @currct, @FD), 0, 0)
        SET @currct = @currct + 1
    END
    
    
    SELECT * FROM #MyTempTable
    
    DROP TABLE #MyTempTable
    
  7. ==============================

    7.SQL Server 2000에이 유래 포스트 외모 일시적으로 시작 및 종료 날짜의 오프 계산 된 날짜를 생성하는 방법을 약속. 그것은 동일하지만 매우 유사 아니다. 이 게시물이 필요한 경우, 날짜를 절단에 아주 깊이있는 답을 가지고있다.

    SQL Server 2000에이 유래 포스트 외모 일시적으로 시작 및 종료 날짜의 오프 계산 된 날짜를 생성하는 방법을 약속. 그것은 동일하지만 매우 유사 아니다. 이 게시물이 필요한 경우, 날짜를 절단에 아주 깊이있는 답을 가지고있다.

    이 질문에 경우 사람의 비틀 거림과 PostgreSQL을 대신 SQL 서버 2000에서 일하고, 여기 당신이 그것을 할 수있는 방법은 ...

    PostgreSQL은 간지 시리즈 생성 기능을 갖는다. 귀하의 예를 들어, 당신은 거기에서 그룹과 매치업을 다음 대신 전체 일정 테이블을 생성하는 모든 일의이 시리즈를 사용하고 있습니다.

    SELECT current_date + s.a AS dates FROM generate_series(0,14,7) AS s(a);
       dates
    ------------
     2004-02-05
     2004-02-12
     2004-02-19
    (3 rows)
    
    SELECT * FROM generate_series('2008-03-01 00:00'::timestamp,
                                  '2008-03-04 12:00', '10 hours');
       generate_series   
    ---------------------
     2008-03-01 00:00:00
     2008-03-01 10:00:00
     2008-03-01 20:00:00
     2008-03-02 06:00:00
     2008-03-02 16:00:00
     2008-03-03 02:00:00
     2008-03-03 12:00:00
     2008-03-03 22:00:00
     2008-03-04 08:00:00
    (9 rows)
    

    나는 또한 쉽게 달력 시리즈의 date_trunc 버전과 일치에 아마 원래 쿼리를 리팩토링에 truncator 필드의 '달'을 사용하여 PostgreSQL의에서 date_trunc로 보일 것이다.

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

    8.

    select top (datediff(D,@start,@end)) dateadd(D,id-1,@start)
    from BIG_TABLE_WITH_NO_JUMPS_IN_ID
    
  9. ==============================

    9.

    declare @start datetime
    set @start = '2016-09-01'
    declare @end datetime
    set @end = '2016-09-30'
    
    create table #Date
    (
        table_id int identity(1,1) NOT NULL,
        counterDate datetime NULL
    );
    
    insert into #Date select top (datediff(D,@start,@end)) NULL from SOME_TABLE
    update #Date set counterDate = dateadd(D,table_id - 1, @start)
    

    위의 코드는 시작과 끝 사이의 모든 날짜와 테이블을 채워야한다. 그런 다음 바로 필요한 모든 날짜를 얻기 위해이 테이블에 결합 할 것입니다. 당신은 매월 특정 일을 필요로하는 경우, 대신 한 달에 DATEADD 수 있습니다.

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

    10.1 년에 각 달의 날짜를 포함하는 테이블 변수를 만듭니다

    1 년에 각 달의 날짜를 포함하는 테이블 변수를 만듭니다

    declare @months table (reportMonth date, PRIMARY KEY (reportMonth));
    declare @start date = '2018', @month int = 0; -- base 0 month
    while (@offset < 12)
    begin
        insert into @reportMonths select dateAdd(month, @offset, @start);
        select @offset = @offset + 1; 
    end
    
  11. from https://stackoverflow.com/questions/6125504/how-can-i-generate-a-temporary-table-filled-with-dates-in-sql-server-2000 by cc-by-sa and MIT license