programing

SQL을 사용하여 날짜 범위 생성

sourcejob 2023. 2. 23. 22:45
반응형

SQL을 사용하여 날짜 범위 생성

날짜 매개 변수를 함수에 넣는 SQL 쿼리가 있으며, 이를 작년 매일 실행해야 합니다.

지난 365일 목록을 생성하여 이를 위해 스트레이트업 SQL을 사용할 수 있도록 하려면 어떻게 해야 합니까?

분명히 목록 0을 생성하고 있습니다.364도 잘 될 거야. 난 항상 할 수 있으니까:

SELECT SYSDATE - val FROM (...);

큰 테이블이나 ALL_OBJECTs 테이블을 사용할 필요가 없습니다.

SELECT TRUNC (SYSDATE - ROWNUM) dt
  FROM DUAL CONNECT BY ROWNUM < 366

효과가 있을 거야

최근에 비슷한 문제가 있어서 다음과 같은 간단한 질문으로 해결했습니다.

SELECT
  (to_date(:p_to_date,'DD-MM-YYYY') - level + 1) AS day
FROM
  dual
CONNECT BY LEVEL <= (to_date(:p_to_date,'DD-MM-YYYY') - to_date(:p_from_date,'DD-MM-YYYY') + 1);

SELECT
  (to_date('01-05-2015','DD-MM-YYYY') - level + 1) AS day
FROM
  dual
CONNECT BY LEVEL <= (to_date('01-05-2015','DD-MM-YYYY') - to_date('01-04-2015','DD-MM-YYYY') + 1);

결과

01-05-2015 00:00:00
30-04-2015 00:00:00
29-04-2015 00:00:00
28-04-2015 00:00:00
27-04-2015 00:00:00
26-04-2015 00:00:00
25-04-2015 00:00:00
24-04-2015 00:00:00
23-04-2015 00:00:00
22-04-2015 00:00:00
21-04-2015 00:00:00
20-04-2015 00:00:00
19-04-2015 00:00:00
18-04-2015 00:00:00
17-04-2015 00:00:00
16-04-2015 00:00:00
15-04-2015 00:00:00
14-04-2015 00:00:00
13-04-2015 00:00:00
12-04-2015 00:00:00
11-04-2015 00:00:00
10-04-2015 00:00:00
09-04-2015 00:00:00
08-04-2015 00:00:00
07-04-2015 00:00:00
06-04-2015 00:00:00
05-04-2015 00:00:00
04-04-2015 00:00:00
03-04-2015 00:00:00
02-04-2015 00:00:00
01-04-2015 00:00:00
 SELECT (sysdate-365 + (LEVEL -1)) AS DATES
 FROM DUAL connect by level <=( sysdate-(sysdate-365))

sysdate 및 sysdate-date 대신 'from' 및 'to' 날짜가 대체될 경우 출력은 에서 날짜까지의 날짜 범위가 됩니다.

Oracle에서 자주 사용되는 방법은 다음과 같습니다.

select trunc(sysdate)-rn
from
(   select rownum rn
    from   dual
    connect by level <= 365)
/

개인적으로는 어플리케이션에 날짜 리스트가 필요한 경우 표를 작성하거나 100만 개까지의 정수가 포함된 표를 만듭니다.이러한 일에는 사용할 수 있습니다.

데이터 사전 개체에 대한 기존의 큰 테이블이나 복잡한 시스템 뷰에 의존하지 않습니다.

SELECT c1 from dual
  MODEL DIMENSION BY (1 as rn)  MEASURES (sysdate as c1)
  RULES ITERATE (365) 
  (c1[ITERATION_NUMBER]=SYSDATE-ITERATION_NUMBER)
order by 1

1년 반 정도 늦었지만, 후세를 위해 Teradata를 위한 버전을 소개합니다.

SELECT calendar_date 
FROM SYS_CALENDAR.Calendar
WHERE SYS_CALENDAR.Calendar.calendar_date between '2010-01-01' (date) and '2010-01-03' (date)

날짜 범위는 1996년 12월 31일부터 2020년 12월 31일까지입니다.

SELECT dt, to_char(dt, 'MM/DD/YYYY') as date_name, 
  EXTRACT(year from dt) as year, 
  EXTRACT(year from fiscal_dt) as fiscal_year,
  initcap(to_char(dt, 'MON')) as month,
  to_char(dt, 'YYYY')        || ' ' || initcap(to_char(dt, 'MON')) as year_month,
  to_char(fiscal_dt, 'YYYY') || ' ' || initcap(to_char(dt, 'MON')) as fiscal_year_month,
  EXTRACT(year from dt)*100        + EXTRACT(month from dt) as year_month_id,
  EXTRACT(year from fiscal_dt)*100 + EXTRACT(month from fiscal_dt) as fiscal_year_month_id,
  to_char(dt, 'YYYY')        || ' Q' || to_char(dt, 'Q') as quarter,
  to_char(fiscal_dt, 'YYYY') || ' Q' || to_char(fiscal_dt, 'Q') as fiscal_quarter
  --, EXTRACT(day from dt) as day_of_month, to_char(dt, 'YYYY-WW') as week_of_year, to_char(dt, 'D') as day_of_week
  FROM (
    SELECT dt, add_months(dt, 6) as fiscal_dt --starts July 1st
    FROM (
      SELECT TO_DATE('12/31/1996', 'mm/dd/yyyy') + ROWNUM as dt 
      FROM DUAL CONNECT BY ROWNUM < 366 * 30 --30 years
    )
    WHERE dt <= TO_DATE('12/31/2020', 'mm/dd/yyyy')
  )

아하하, 이렇게 하기 위해 제가 생각해낸 재미있는 방법이 있습니다.

select SYSDATE - ROWNUM
from shipment_weights sw
where ROWNUM < 365;

여기서 shippment_timeout은 큰 테이블입니다.

저도 같은 요구였습니다.이것만 사용하겠습니다.사용자는 일정 범위를 제한하는 일수를 입력합니다.

  SELECT DAY, offset
    FROM (SELECT to_char(SYSDATE, 'DD-MON-YYYY') AS DAY, 0 AS offset
            FROM DUAL
          UNION ALL
          SELECT to_char(SYSDATE - rownum, 'DD-MON-YYYY'), rownum
            FROM all_objects d)
            where offset <= &No_of_days

나는 위의 결과 세트를 운전 뷰로 사용한다.LEFT OUTER JOIN날짜가 있는 테이블을 포함하는 다른 보기와 함께.

6개월 후 일주일 후

SELECT (date'2015-08-03' + (LEVEL-1)) AS DATES
 FROM DUAL 
 where ROWNUM < 8
 connect by level <= (sysdate-date'2015-08-03'); 

ROWNUM을 생략하면 값에 관계없이 50행만 얻을 수 있습니다.

늦더라도 안 하느니보다는 낫다.다음은 (이 게시물을 읽은 후) (a) 금월 1일 ~ 오늘까지의 날짜 목록과 (b) 지난 2개월 동안의 모든 날짜를 포함하는 날짜 목록을 반환하기 위한 방법입니다.

select (sysdate +1 - rownum) dt 
from dual 
 connect by rownum <= (sysdate - add_months(sysdate - extract(day from sysdate),-2));

"-2"는 포함할 전체 달의 수입니다.예를 들어, 7월 10일에 이 SQL은 5월 1일부터 7월 10일까지의 모든 날짜 목록을 반환합니다. 즉, 2개의 완전한 이전 달과 현재의 부분 달입니다.

오늘부터 365일 후를 얻는 또 다른 간단한 방법은 다음과 같습니다.

SELECT (TRUNC(sysdate) + (LEVEL-366)) AS DATE_ID
FROM DUAL connect by level <=( (sysdate)-(sysdate-366));

SQL Server, Oracle 또는 MySQL에서 작동해야 하는 몇 가지 코드는 다음과 같습니다.

SELECT current_timestamp - CAST(d1.digit + d2.digit + d3.digit as int)
FROM 
(
    SELECT digit
    FROM
    (
        select '1' as digit
        union select '2'
        union select '3'
        union select '4'
        union select '5'
        union select '6'
        union select '7'
        union select '8'
        union select '9'
        union select '0'
    ) digits
) d1
CROSS JOIN
(
    SELECT digit
    FROM
    (
        select '1' as digit
        union select '2'
        union select '3'
        union select '4'
        union select '5'
        union select '6'
        union select '7'
        union select '8'
        union select '9'
        union select '0'
    ) digits
) d2
CROSS JOIN
(
    SELECT digit
    FROM
    (
        select '1' as digit
        union select '2'
        union select '3'
        union select '4'
        union select '5'
        union select '6'
        union select '7'
        union select '8'
        union select '9'
        union select '0'
    ) digits
) d3
WHERE CAST(d1.digit + d2.digit + d3.digit as int) < 365
ORDER BY d1.digit, d2.digit, d3.digit -- order not really needed here

숫자 테이블을 재사용할 수 있는 교차 플랫폼 구문을 제공할 수 있다면 보너스 포인트입니다.

스케줄 앱에서 자주 하는 일이라 파이프라인 테이블 함수를 만들었습니다.가끔 며칠, 몇 시간, 15분씩 시간이 필요할 때가 있어요.코드가 패키지에 포함되어 있기 때문에 이 기능은 제가 사용하는 기능과 완전히 다릅니다.하지만 여기서는 2020년 1월 1일부터 2020년 1월 10일까지의 날짜를 얻을 수 있습니다.

SELECT
    days.date_time
FROM
    table(between_times(TO_DATE('2020-01-01'),TO_DATE('2020-01-10'),(60*24), 'Y')) days

파이프라인 기능:

function between_times(i_start_time TIMESTAMP, i_end_time TIMESTAMP, i_interval_in_minutes NUMBER, include_end_time VARCHAR2 := 'N')
  RETURN DateTableType  PIPELINED
  AS
    time_counter TIMESTAMP := i_start_time;
  BEGIN
    IF i_start_time IS NULL OR i_end_time IS NULL or i_start_time > i_end_time OR i_interval_in_minutes IS NULL OR
      i_interval_in_minutes <= 0 THEN
        RETURN;
      END IF;
      LOOP

        -- by default does not include end time
        if (include_end_time = 'Y') THEN
          exit when time_counter > i_end_time;
        ELSE
          exit when time_counter >= i_end_time;
        END IF;
        
        
        pipe row(DateType( time_counter ));     
        time_counter := time_counter + i_interval_in_minutes/(60*24);
        
      END LOOP;
      
      EXCEPTION  WHEN NO_DATA_NEEDED THEN NULL;      
  END;
WITH Date_Table (Dates, Heading) AS  -- Using Oracle SQL
(SELECT  TRUNC(SYSDATE) Dates, '  Start' as Heading FROM dual
UNION ALL
SELECT TRUNC(DATES-1) ,  '  Inside recursion' as Heading FROM Date_Table
WHERE Dates > sysdate-365 )  -- Go back one year
SELECT TO_CHAR(Dates,'MM/DD/YYYY') 
FROM Date_Table
ORDER BY Dates DESC;

숫자 테이블을 재사용할 수 있는 답변은 없지만 SQL Server에서 작동하며 좀 더 빠른 코드 샘플이 있습니다.

print("code sample");

select  top 366 current_timestamp - row_number() over( order by l.A * r.A) as DateValue
from (
select  1 as A union
select  2 union
select  3 union
select  4 union
select  5 union
select  6 union
select  7 union
select  8 union
select  9 union
select  10 union
select  11 union
select  12 union
select  13 union
select  14 union
select  15 union
select  16 union
select  17 union
select  18 union
select  19 union
select  20 union
select  21 
) l
cross join (
select 1 as A union
select 2 union
select 3 union
select 4 union
select 5 union
select 6 union
select 7 union
select 8 union
select 9 union
select 10 union
select 11 union
select 12 union
select 13 union
select 14 union
select 15 union
select 16 union
select 17 union
select 18
) r
print("code sample");

이 쿼리는 현재 4000일 미래 및 5000일 과거 날짜 목록을 생성합니다(http://blogs.x2line.com/al/articles/207.aspx)에서 영감을 받았습니다.

SELECT * FROM (SELECT
    (CONVERT(SMALLDATETIME, CONVERT(CHAR,GETDATE() ,103)) + 4000 -
                n4.num * 1000 -
                n3.num * 100 -
                n2.num * 10 -
                n1.num) AS Date, 
    year(CONVERT(SMALLDATETIME, CONVERT(CHAR,GETDATE() ,103)) + 4000 -
                n4.num * 1000 -
                n3.num * 100 -
                n2.num * 10 -
                n1.num) as Year,
    month(CONVERT(SMALLDATETIME, CONVERT(CHAR,GETDATE() ,103)) + 4000 -
                n4.num * 1000 -
                n3.num * 100 -
                n2.num * 10 -
                n1.num) as Month,
    day(CONVERT(SMALLDATETIME, CONVERT(CHAR,GETDATE() ,103)) + 4000 -
                n4.num * 1000 -
                n3.num * 100 -
                n2.num * 10 -
                n1.num) as Day
           FROM (SELECT 0 AS num 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) n1
               ,(SELECT 0 AS num 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) n2
               ,(SELECT 0 AS num 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) n3  
               ,(SELECT 0 AS num 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) n4
        ) GenCalendar  ORDER BY 1

언급URL : https://stackoverflow.com/questions/418318/generate-a-range-of-dates-using-sql

반응형