복붙노트

[SQL] 두 날짜 사이의 날짜의 목록을 가져옵니다

SQL

두 날짜 사이의 날짜의 목록을 가져옵니다

표준 MySQL의 기능을 사용하면 두 날짜 사이의 일의 목록을 반환하는 쿼리를 작성하는 방법이있다.

예를 들어 2009-01-01 주어 2009-01-13 그것은 값으로 한 열 테이블을 반환합니다 :

 2009-01-01 
 2009-01-02 
 2009-01-03
 2009-01-04 
 2009-01-05
 2009-01-06
 2009-01-07
 2009-01-08 
 2009-01-09
 2009-01-10
 2009-01-11
 2009-01-12
 2009-01-13

편집 : 그것은 내가 명확하지 않은 나타납니다. 나는이 목록을 생성합니다. 나는 (날짜 별) 데이터베이스에 저장된 값을 가지고 있지만 어떤 일에 가입하고이를 처리합니다 (I이 몇 가지의 오른쪽에서 널 (null)을 기대하고 위와 같이 날짜 목록에 가입 그들을 왼쪽 외부에 집계 할 ).

해결법

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

    1.내가 가입 한 후, 당신은 임시 테이블 이름 time_intervals에 필요한 간격을 생성하기 위해이 저장 프로 시저를 사용하여 임시 time_intervals 테이블과 데이터 테이블을 집계합니다.

    내가 가입 한 후, 당신은 임시 테이블 이름 time_intervals에 필요한 간격을 생성하기 위해이 저장 프로 시저를 사용하여 임시 time_intervals 테이블과 데이터 테이블을 집계합니다.

    절차는 당신이 그것을에 지정된 참조 모든 다른 유형의 간격을 생성 할 수 있습니다 :

    call make_intervals('2009-01-01 00:00:00','2009-01-10 00:00:00',1,'DAY')
    .
    select * from time_intervals  
    .
    interval_start      interval_end        
    ------------------- ------------------- 
    2009-01-01 00:00:00 2009-01-01 23:59:59 
    2009-01-02 00:00:00 2009-01-02 23:59:59 
    2009-01-03 00:00:00 2009-01-03 23:59:59 
    2009-01-04 00:00:00 2009-01-04 23:59:59 
    2009-01-05 00:00:00 2009-01-05 23:59:59 
    2009-01-06 00:00:00 2009-01-06 23:59:59 
    2009-01-07 00:00:00 2009-01-07 23:59:59 
    2009-01-08 00:00:00 2009-01-08 23:59:59 
    2009-01-09 00:00:00 2009-01-09 23:59:59 
    .
    call make_intervals('2009-01-01 00:00:00','2009-01-01 02:00:00',10,'MINUTE')
    . 
    select * from time_intervals
    .  
    interval_start      interval_end        
    ------------------- ------------------- 
    2009-01-01 00:00:00 2009-01-01 00:09:59 
    2009-01-01 00:10:00 2009-01-01 00:19:59 
    2009-01-01 00:20:00 2009-01-01 00:29:59 
    2009-01-01 00:30:00 2009-01-01 00:39:59 
    2009-01-01 00:40:00 2009-01-01 00:49:59 
    2009-01-01 00:50:00 2009-01-01 00:59:59 
    2009-01-01 01:00:00 2009-01-01 01:09:59 
    2009-01-01 01:10:00 2009-01-01 01:19:59 
    2009-01-01 01:20:00 2009-01-01 01:29:59 
    2009-01-01 01:30:00 2009-01-01 01:39:59 
    2009-01-01 01:40:00 2009-01-01 01:49:59 
    2009-01-01 01:50:00 2009-01-01 01:59:59 
    .
    I specified an interval_start and interval_end so you can aggregate the 
    data timestamps with a "between interval_start and interval_end" type of JOIN.
    .
    Code for the proc:
    .
    -- drop procedure make_intervals
    .
    CREATE PROCEDURE make_intervals(startdate timestamp, enddate timestamp, intval integer, unitval varchar(10))
    BEGIN
    -- *************************************************************************
    -- Procedure: make_intervals()
    --    Author: Ron Savage
    --      Date: 02/03/2009
    --
    -- Description:
    -- This procedure creates a temporary table named time_intervals with the
    -- interval_start and interval_end fields specifed from the startdate and
    -- enddate arguments, at intervals of intval (unitval) size.
    -- *************************************************************************
       declare thisDate timestamp;
       declare nextDate timestamp;
       set thisDate = startdate;
    
       -- *************************************************************************
       -- Drop / create the temp table
       -- *************************************************************************
       drop temporary table if exists time_intervals;
       create temporary table if not exists time_intervals
          (
          interval_start timestamp,
          interval_end timestamp
          );
    
       -- *************************************************************************
       -- Loop through the startdate adding each intval interval until enddate
       -- *************************************************************************
       repeat
          select
             case unitval
                when 'MICROSECOND' then timestampadd(MICROSECOND, intval, thisDate)
                when 'SECOND'      then timestampadd(SECOND, intval, thisDate)
                when 'MINUTE'      then timestampadd(MINUTE, intval, thisDate)
                when 'HOUR'        then timestampadd(HOUR, intval, thisDate)
                when 'DAY'         then timestampadd(DAY, intval, thisDate)
                when 'WEEK'        then timestampadd(WEEK, intval, thisDate)
                when 'MONTH'       then timestampadd(MONTH, intval, thisDate)
                when 'QUARTER'     then timestampadd(QUARTER, intval, thisDate)
                when 'YEAR'        then timestampadd(YEAR, intval, thisDate)
             end into nextDate;
    
          insert into time_intervals select thisDate, timestampadd(MICROSECOND, -1, nextDate);
          set thisDate = nextDate;
       until thisDate >= enddate
       end repeat;
    
     END;
    

    내가 SQL Server에 대한 유사한 기능을 내장이 게시물의 하단에 비슷한 예를 들어 데이터 시나리오.

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

    2.MSSQL 위해 당신은이를 사용할 수 있습니다. 그것은 아주 빠르다.

    MSSQL 위해 당신은이를 사용할 수 있습니다. 그것은 아주 빠르다.

    당신은 테이블 값 함수에서이 작업을 마무리 또는 변수로 시작 및 종료 날짜에 PROC 및 구문 분석을 저장 할 수 있습니다.

    DECLARE @startDate DATETIME
    DECLARE @endDate DATETIME
    
    SET @startDate = '2011-01-01'
    SET @endDate = '2011-01-31';
    
    WITH dates(Date) AS 
    (
        SELECT @startdate as Date
        UNION ALL
        SELECT DATEADD(d,1,[Date])
        FROM dates 
        WHERE DATE < @enddate
    )
    
    SELECT Date
    FROM dates
    OPTION (MAXRECURSION 0)
    GO
    
  3. ==============================

    3.우리는 우리가 데이터 없었다 그 일에 대해보고 싶다고에서 BIRT 보고서와 비슷한 문제가 있었다. 그 날짜에 대한 항목이 있었다 없기 때문에, 우리에게 가장 쉬운 해결책은 범위를 얻거나 해당 날짜에 대해 0 값을 얻기 위해 가입하는 모든 날짜와 사용을 저장하는 간단한 테이블을 만드는 것이 었습니다.

    우리는 우리가 데이터 없었다 그 일에 대해보고 싶다고에서 BIRT 보고서와 비슷한 문제가 있었다. 그 날짜에 대한 항목이 있었다 없기 때문에, 우리에게 가장 쉬운 해결책은 범위를 얻거나 해당 날짜에 대해 0 값을 얻기 위해 가입하는 모든 날짜와 사용을 저장하는 간단한 테이블을 만드는 것이 었습니다.

    우리는 테이블이 미래 오년을 채워 될 수 있도록 매월를 실행하는 작업을해야합니다. 테이블은 이렇게 만들어집니다

    create table all_dates (
        dt date primary key
    );
    

    의심의 여지가 다른 DBMS로이 작업을 수행하는 마법의 교묘 한 방법이있다 '하지만 우리는 항상 가장 간단한 솔루션을 선택. 테이블에 대한 스토리지 요구 사항을 최소화하고 그것은 쿼리가 훨씬 간단하고 휴대 있습니다. 솔루션 이런 종류의 성능 포인트의보기는 데이터에 대한 당 행 계산을 필요로하지 않기 때문에에서 거의 항상 낫다.

    다른 옵션은 (우리가 전에이 사용했습니다) 모든 일에 대한 테이블의 항목이있다 있도록하는 것입니다. 우리는 정기적으로 테이블을 휩쓸 존재하지 않았다 날짜 및 / 또는 시간에 대해 0 항목을 추가했다. 이것은 귀하의 경우 옵션이 될 수 없습니다, 그것은 저장된 데이터에 따라 달라집니다.

    당신이 정말로 그것을 채워 all_dates 테이블을 유지하는 번거 로움을 생각하면, 저장 프로 시저는 그 날짜를 포함하는 데이터 집합을 반환하는 길을 가야하는 것입니다. 당신이 범위를가 아니라 단지 테이블에서 미리 계산 된 데이터를 당겨보다라고 모든 시간을 계산해야하기 때문에 이것은 거의 확실하게 느려집니다.

    하지만, 솔직히 말해서, 당신이 어떤 심각한 데이터 저장 문제없이 천년의 테이블을 채울 수 - 365000 (예를 들어) 16 바이트 날짜 플러스 안전을 위해 오버 헤드 날짜 플러스 20 %를 중복 인덱스를, 나는 약에 추정 것 14M [365,000 * 16 * 2 * 120 = 14,016,000 바이트])에 대해, 일의 방식에서 소문자 테이블.

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

    4.이 같은 MySQL을의 사용자 변수를 사용할 수 있습니다 :

    이 같은 MySQL을의 사용자 변수를 사용할 수 있습니다 :

    SET @num = -1;
    SELECT DATE_ADD( '2009-01-01', interval @num := @num+1 day) AS date_sequence, 
    your_table.* FROM your_table
    WHERE your_table.other_column IS NOT NULL
    HAVING DATE_ADD('2009-01-01', interval @num day) <= '2009-01-13'
    

    @num은 -1 당신이 그것에 당신이 그것을 사용하는 첫 번째 시간을 추가하기 때문이다. 또한, 당신은 각 행에 대해 두 번 사용자 변수의 증가를 만들기 때문에 "date_sequence을 HAVING"사용할 수 없습니다.

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

    5.이 답변에서 아이디어를 차용, 당신은 9 0 테이블을 설정하고 날짜 목록을 생성하기 위해 그것을 사용할 수 있습니다.

    이 답변에서 아이디어를 차용, 당신은 9 0 테이블을 설정하고 날짜 목록을 생성하기 위해 그것을 사용할 수 있습니다.

    CREATE TABLE num (i int);
    INSERT INTO num (i) VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9);
    
    select adddate('2009-01-01', numlist.id) as `date` from
    (SELECT n1.i + n10.i*10 + n100.i*100 AS id
       FROM num n1 cross join num as n10 cross join num as n100) as numlist
    where adddate('2009-01-01', numlist.id) <= '2009-01-13';
    

    이는 1000 날짜까지의 목록을 생성 할 수 있습니다. 더 큰 이동해야하는 경우, 다른 크로스는 내부 쿼리에 조인 추가 할 수 있습니다.

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

    6.액세스 (또는 SQL 언어)에 대한

    액세스 (또는 SQL 언어)에 대한

    쉬운!

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

    7.일반적으로 사람은 당신이 보통이에 대한 몇 가지 변화에 바로이 목적을 위해 주위를 유지 보조 번호 테이블을 사용합니다 :

    일반적으로 사람은 당신이 보통이에 대한 몇 가지 변화에 바로이 목적을 위해 주위를 유지 보조 번호 테이블을 사용합니다 :

    SELECT *
    FROM (
        SELECT DATEADD(d, number - 1, '2009-01-01') AS dt
        FROM Numbers
        WHERE number BETWEEN 1 AND DATEDIFF(d, '2009-01-01', '2009-01-13') + 1
    ) AS DateRange
    LEFT JOIN YourStuff
        ON DateRange.dt = YourStuff.DateColumn
    

    나는 등 테이블 반환 함수와 변화를 보았다

    또한 날짜의 영구적 인 목록을 유지할 수 있습니다. 우리는 우리의 데이터웨어 하우스뿐만 아니라 일의 시간의 목록이 있습니다.

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

    8.그럼 SQL 서버에서 지정된 두 날짜 사이의 날짜를 찾는 방법은 http://ektaraval.blogspot.com/2010/09/writing-recursive-query-to-find-out-all.html에 설명입니다

    그럼 SQL 서버에서 지정된 두 날짜 사이의 날짜를 찾는 방법은 http://ektaraval.blogspot.com/2010/09/writing-recursive-query-to-find-out-all.html에 설명입니다

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

    9.

    CREATE FUNCTION [dbo].[_DATES]
    (
        @startDate DATETIME,
        @endDate DATETIME
    )
    RETURNS 
    @DATES TABLE(
        DATE1 DATETIME
    )
    AS
    BEGIN
        WHILE @startDate <= @endDate
        BEGIN 
            INSERT INTO @DATES (DATE1)
                SELECT @startDate   
        SELECT @startDate = DATEADD(d,1,@startDate) 
        END
    RETURN
    END
    
  10. ==============================

    10.우리는 당신이 유용 할 것이다 우리의 HRMS 시스템이 사용

    우리는 당신이 유용 할 것이다 우리의 HRMS 시스템이 사용

    SELECT CAST(DAYNAME(daydate) as CHAR) as dayname,daydate
        FROM
        (select CAST((date_add('20110101', interval H.i*100 + T.i*10 + U.i day) )as DATE) as daydate
          from erp_integers as H
        cross
          join erp_integers as T
        cross
          join erp_integers as U
         where date_add('20110101', interval H.i*100 + T.i*10 + U.i day ) <= '20110228'
        order
            by daydate ASC
            )Days
    
  11. ==============================

    11.이 솔루션은 5.0와 협력 테이블 만들기 - MYTABLE. 스키마는 중요하지 않습니다. 중요한 것은 그것의 행의 수입니다. 1 ~ 10 - 그래서, 당신은 10 행, 값 유형 INT의 한 열을 유지할 수 있습니다.

    이 솔루션은 5.0와 협력 테이블 만들기 - MYTABLE. 스키마는 중요하지 않습니다. 중요한 것은 그것의 행의 수입니다. 1 ~ 10 - 그래서, 당신은 10 행, 값 유형 INT의 한 열을 유지할 수 있습니다.

    SQL :

    set @tempDate=date('2011-07-01') - interval 1 day;
    select
    date(@tempDate := (date(@tempDate) + interval 1 day)) as theDate
    from mytable x,mytable y
    group by theDate
    having theDate <= '2011-07-31';
    

    한정: 위의 쿼리에서 반환 날짜의 최대 수는있을 것입니다 (MYTABLE 행) (MYTABLE 행) * = 10 * 10 = 100.

    당신은 SQL의 형태 부분을 변경하여이 범위를 증가시킬 수있다 : MYTABLE X에서 MYTABLE Y, Z MYTABLE 따라서, 범위 등 10 * 10 * 10 = 1000 일.

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

    12.MariaDB에서> = 10.3와 MySQL> = 8.0 새로운 재귀 (공통 테이블 식) 기능을 사용하여 우아한 솔루션입니다.

    MariaDB에서> = 10.3와 MySQL> = 8.0 새로운 재귀 (공통 테이블 식) 기능을 사용하여 우아한 솔루션입니다.

    WITH RECURSIVE t as (
        select '2019-01-01' as dt
      UNION
        SELECT DATE_ADD(t.dt, INTERVAL 1 DAY) FROM t WHERE DATE_ADD(t.dt, INTERVAL 1 DAY) <= '2019-04-30'
    )
    select * FROM t;
    

    위의 반환 '2019년 1월 1일'와 '2019년 4월 30일'사이의 날짜의 테이블.

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

    13.두 개의 매개 변수 a_begin 및 a_end 걸리는 저장 프로 시저를 만듭니다. 이 t라는 내에서 임시 테이블을 만들고, 변수 d를 선언, 할당 a_begin에 D 및 t에 WHILE 루프 삽입 D를 실행하고 ADDDATE 함수를 호출하면 값 d를 증가 할 수 있습니다. 마지막으로 t SELECT * FROM.

    두 개의 매개 변수 a_begin 및 a_end 걸리는 저장 프로 시저를 만듭니다. 이 t라는 내에서 임시 테이블을 만들고, 변수 d를 선언, 할당 a_begin에 D 및 t에 WHILE 루프 삽입 D를 실행하고 ADDDATE 함수를 호출하면 값 d를 증가 할 수 있습니다. 마지막으로 t SELECT * FROM.

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

    14.나는이 비슷한을 사용합니다 :

    나는이 비슷한을 사용합니다 :

    DECLARE @DATEFROM AS DATETIME
    DECLARE @DATETO AS DATETIME
    DECLARE @HOLDER TABLE(DATE DATETIME)
    
    SET @DATEFROM = '2010-08-10'
    SET @DATETO = '2010-09-11'
    
    INSERT INTO
        @HOLDER
            (DATE)
    VALUES
        (@DATEFROM)
    
    WHILE @DATEFROM < @DATETO
    BEGIN
    
        SELECT @DATEFROM = DATEADD(D, 1, @DATEFROM)
        INSERT 
        INTO
            @HOLDER
                (DATE)
        VALUES
            (@DATEFROM)
    END
    
    SELECT 
        DATE
    FROM
        @HOLDER
    

    그런 다음 @HOLDER 변수 테이블은 당신의 마음의 콘텐츠에 가입 할 준비가 그 두 날짜 사이에 하루 씩 증가 모든 날짜를 보유하고 있습니다.

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

    15.나는 꽤 오랫동안이와 싸우고 있었어요. 나는 솔루션을 검색 할 때이 구글의 첫 번째 히트이기 때문에, 내가 지금까지 들어 왔 곳에 나 게시 할 수 있습니다.

    나는 꽤 오랫동안이와 싸우고 있었어요. 나는 솔루션을 검색 할 때이 구글의 첫 번째 히트이기 때문에, 내가 지금까지 들어 왔 곳에 나 게시 할 수 있습니다.

    SET @d := '2011-09-01';
    SELECT @d AS d, cast( @d := DATE_ADD( @d , INTERVAL 1 DAY ) AS DATE ) AS new_d
      FROM [yourTable]
      WHERE @d <= '2012-05-01';
    

    데이터베이스에서 테이블 [yourTable]를 교체합니다. 트릭은 당신이해야 선택 테이블의 행 수> = 당신이 원하는 날짜의 수를 반환 할 것입니다. 나는 DUAL 자리 테이블을 사용했지만, 그것은 단지 하나 개의 행을 반환합니다.

  16. ==============================

    16.

    select * from table_name where col_Date between '2011/02/25' AND DATEADD(s,-1,DATEADD(d,1,'2011/02/27'))
    

    여기서, 먼저 현재 endDate가에 하루를 추가, 그것은 다음 종료 날짜 2011-02-27 23시 59분 59초를 만들기 위해 1 초 빼기, 2011-02-28 00:00:00됩니다. 이렇게하면 주어진 간격 사이의 모든 날짜를 얻을 수 있습니다.

    산출: 2011/02/25 2011년 2월 26일 2011/02/27

  17. ==============================

    17.

    DELIMITER $$  
    CREATE PROCEDURE popula_calendario_controle()
       BEGIN
          DECLARE a INT Default 0;
          DECLARE first_day_of_year DATE;
          set first_day_of_year = CONCAT(DATE_FORMAT(curdate(),'%Y'),'-01-01');
          one_by_one: LOOP
             IF dayofweek(adddate(first_day_of_year,a)) <> 1 THEN
                INSERT INTO calendario.controle VALUES(null,150,adddate(first_day_of_year,a),adddate(first_day_of_year,a),1);
             END IF;
             SET a=a+1;
             IF a=365 THEN
                LEAVE one_by_one;
             END IF;
          END LOOP one_by_one;
    END $$
    

    이 절차는 단지 '시작'의 일 "끝"대체 값, 지금까지 올해의 시작 부분에서 모든 날짜를 삽입합니다, 당신은 갈 준비!

  18. ==============================

    18.나는 통계 두 날짜 사이의 모든 개월 목록을 필요로했다. 2 개의 날짜는 가입에서 시작과 ENDDATE입니다. 목록 쇼 모든 개월 매달 구독의 양 그래서.

    나는 통계 두 날짜 사이의 모든 개월 목록을 필요로했다. 2 개의 날짜는 가입에서 시작과 ENDDATE입니다. 목록 쇼 모든 개월 매달 구독의 양 그래서.

    MYSQL

    CREATE PROCEDURE `get_amount_subscription_per_month`()
    BEGIN
       -- Select the ultimate start and enddate from subscribers
       select @startdate := min(DATE_FORMAT(a.startdate, "%Y-%m-01")), 
              @enddate := max(DATE_FORMAT(a.enddate, "%Y-%m-01")) + interval 1 MONTH
       from subscription a;
    
       -- Tmp table with all months (dates), you can always format them with DATE_FORMAT) 
       DROP TABLE IF EXISTS tmp_months;
       create temporary table tmp_months (
          year_month date,
          PRIMARY KEY (year_month)
       );
    
    
       set @tempDate=@startdate;  #- interval 1 MONTH;
    
       -- Insert every month in tmp table
       WHILE @tempDate <= @enddate DO
         insert into tmp_months (year_month) values (@tempDate);
         set @tempDate = (date(@tempDate) + interval 1 MONTH);
       END WHILE;
    
       -- All months
       select year_month from tmp_months;
    
       -- If you want the amount of subscription per month else leave it out
       select mnd.year_month, sum(subscription.amount) as subscription_amount
       from tmp_months mnd
       LEFT JOIN subscription ON mnd.year_month >= DATE_FORMAT(subscription.startdate, "%Y-%m-01") and mnd.year_month <= DATE_FORMAT(subscription.enddate, "%Y-%m-01")
       GROUP BY mnd.year_month;
    
     END
    
  19. ==============================

    19.나는 Server 버전을 사용하고 있습니다 : 5.7.11 로그의 MySQL 커뮤니티 서버 (GPL)

    나는 Server 버전을 사용하고 있습니다 : 5.7.11 로그의 MySQL 커뮤니티 서버 (GPL)

    이제 우리는 간단한 방식으로이 문제를 해결합니다.

    나는라는 이름의 테이블을 만들었습니다 "datetable"

    mysql> describe datetable;
    +---------+---------+------+-----+---------+-------+
    | Field   | Type    | Null | Key | Default | Extra |
    +---------+---------+------+-----+---------+-------+
    | colid   | int(11) | NO   | PRI | NULL    |       |
    | coldate | date    | YES  |     | NULL    |       |
    +---------+---------+------+-----+---------+-------+
    2 rows in set (0.00 sec)
    

    지금, 우리는 내 삽입 된 기록을 볼 수 있습니다.

    mysql> select * from datetable;
    +-------+------------+
    | colid | coldate    |
    +-------+------------+
    |   101 | 2015-01-01 |
    |   102 | 2015-05-01 |
    |   103 | 2016-01-01 |
    +-------+------------+
    3 rows in set (0.00 sec)
    

    그리고 두 날짜보다는 그 기간 내 기록을 가져 우리의 쿼리를 여기에.

    mysql> select * from datetable where coldate > '2015-01-01' and coldate < '2016-01-01';
    +-------+------------+
    | colid | coldate    |
    +-------+------------+
    |   102 | 2015-05-01 |
    +-------+------------+
    1 row in set (0.00 sec)
    

    이 많은 사람을 도움이되기를 바랍니다.

  20. from https://stackoverflow.com/questions/510012/get-a-list-of-dates-between-two-dates by cc-by-sa and MIT license