到给定日期的最近日期 - SQL Oracle

时间:2017-10-12 14:38:40

标签: sql oracle

Oracle(SQL) - 我在一个月内(第1天,第10天和第25天)有3个可用日期。我需要一个查询,根据执行查询的日期找出3个日期中最接近的日期。例如,当我在第4次运行查询时,我应该得到第10个作为我的结果,当我在第12次运行时,结果应该是第25次,当我在第27次运行时,结果应该是下个月的第01个。 我正在努力解决逻辑问题。请帮忙..

4 个答案:

答案 0 :(得分:1)

with
     inputs ( dt ) as (
       select to_date( '03/24/2015 11:30:00', 'mm/dd/yyyy hh24:mi:ss') from dual union all
       select to_date( '08/03/2016 07:15:00', 'mm/dd/yyyy hh24:mi:ss') from dual union all
       select to_date( '02/29/2016 22:30:00', 'mm/dd/yyyy hh24:mi:ss') from dual
     )
-- End of simulated inputs (for testing only, not part of the solution).
-- SQL query begins BELOW THIS LINE. Use your actual table and column names.
select dt,
       case when extract(day from dt) < 10 then trunc(dt, 'mm') + interval  '9' day
            when extract(day from dt) < 25 then trunc(dt, 'mm') + interval '24' day
            else add_months(trunc(dt, 'mm'), 1)
       end  as next_std_dt
from   inputs;

DT                   NEXT_STD_DT       
-------------------  -------------------
03/24/2015 11:30:00  03/25/2015 00:00:00
08/03/2016 07:15:00  08/10/2016 00:00:00
02/29/2016 22:30:00  03/01/2016 00:00:00

答案 1 :(得分:0)

WITH mytable(dt) AS
  (SELECT '01'
   FROM dual
   UNION ALL SELECT '10'
   FROM dual
   UNION ALL SELECT '25'
   FROM dual),
     given_dates AS
  (SELECT Trunc (To_date (dt || To_char(sysdate, 'MMYYYY'), 'DDMMYYYY')) dt,
          Trunc(sysdate) cdate
   FROM mytable),
     comp AS
  (SELECT cdate,
          CASE
              WHEN ABS (cdate - dt) < ABS (cdate - Add_months (dt, 1)) THEN dt
              ELSE Add_months (dt, 1)
          END dt_comp
   FROM given_dates)
SELECT dt_comp closest_date
FROM
  (SELECT dt_comp,
          rank() OVER (
                       ORDER BY ABS (cdate - dt_comp)) rn
   FROM comp)
WHERE rn = 1;

答案 2 :(得分:0)

如果使用PL SQL是一个选项,则使用以下查询:

`DECLARE
   curr_month        CHAR(2);
   curr_year         CHAR(4);
   future_date       DATE;
BEGIN
   select to_char(sysdate, 'MM') INTO curr_month from dual;
   select to_char(sysdate, 'YYYY') INTO curr_year from dual;
   future_date := TO_DATE('12' ||  curr_month || curr_year, 'DD/MM/YYYY');
   IF (SYSDATE > future_date) THEN
        {..whatever you want to do...}
   ELSIF (SYSDATE > future_date2) THEN
        {..whatever you want to do...}
   END IF;
END;`

答案 3 :(得分:0)

我相信这比其他解决方案更有效,更简单。

WITH
    possible_dates
    AS
        -- generate the three available dates for the current month
        (SELECT TRUNC (SYSDATE, 'MM') available_date
           FROM DUAL
         UNION ALL
         SELECT TRUNC (SYSDATE, 'MM') + 9
           FROM DUAL
         UNION ALL
         SELECT TRUNC (SYSDATE, 'MM') + 24
           FROM DUAL
         UNION ALL
         SELECT ADD_MONTHS (TRUNC (SYSDATE, 'MM'), 1)
           FROM DUAL),
    delta
    AS
        -- calculate the distance of those available dates
        (SELECT (available_date - SYSDATE) diff, available_date
           FROM possible_dates)
SELECT *
  FROM delta
 WHERE diff = (SELECT MIN (diff)
                 FROM delta
                WHERE diff >= 0);