【问题标题】:Get same day of the same week last year获取去年同一周的同一天
【发布时间】:2015-08-24 13:31:07
【问题描述】:

我正在寻找一种方法来获得与去年相同的特定日期。

我有一张带有日期的表格,并希望在同一天但去年的同一天在第二列中。

示例: 日期:2009 年 6 月 1 日星期一 去年日期:2008 年 6 月 2 日星期一

所以它必须是同一周的同一天,但要早一年。

有没有办法做到这一点?

感谢您的帮助?

【问题讨论】:

  • 你使用哪一周的定义?
  • 同一周数
  • 如果一年有 53 周,而前一年没有,会发生什么?

标签: sql oracle plsql


【解决方案1】:

试试:

select add_months(sysdate, -12) + (to_char(sysdate, 'D') - to_char(add_months(sysdate, -12), 'D'))
from dual

输出:

6/10/2014 12:07:01 PM

今天也是星期二。

【讨论】:

  • 对于日期 February, 29 2016(第 9 周第 2 天),此查询给出 February, 23 2015(第 8 周第 2 天)
  • @kordirko 去年的 23 日是在今年 29 日的 7 天内,这是我理解的 OP 想要的,但也许我误解了
【解决方案2】:

你可以用这个:

SELECT 
    NEXT_DAY(ADD_MONTHS(DATE '2009-06-01', -12)-1, TO_CHAR(DATE '2009-06-01', 'fmDAY')) AS Last_year_day 
FROM dual;

结果:

2008-06-02

当然,它总是返回下一个天,即最坏的情况是 6 天后。

【讨论】:

  • 谢谢,但是这个查询的问题,返回的日期并不总是在同一周示例 01/08/2016(第 31 周)它返回 03/08/2015(第 32 周)
  • 您没有提到任何周限制。在这种情况下,NEXT_DAY(ADD_MONTHS(DATE '2009-06-01', -12)-7, TO_CHAR(DATE '2009-06-01', 'fmDAY')) 应该可以工作。
  • 2015 年 6 月 30 日(第 27 周)出现同样的问题,2014 年 6 月 24 日(第 26 周)返回,谢谢大家。我会尝试寻找其他解决方案。
【解决方案3】:

假设“周”是指 ISO-8601 定义的周,您可以使用将周数转换为日期的函数。

CREATE FUNCTION IsoWeekDate(iso_year IN INTEGER, iso_week IN INTEGER) RETURN DATE AS
BEGIN
   RETURN TRUNC(TO_DATE(iso_year || '0104', 'YYYYMMDD'), 'IW') + 7 * (iso_week - 1);
END IsoWeekDate;

那么你可以这样:

SELECT 
   NEXT_DAY(IsoWeekDate(TO_CHAR(DATE '2009-06-01', 'IYYY')-1, TO_CHAR(DATE '2009-06-01', 'IW'))-1, TO_CHAR(DATE '2009-06-01', 'fmDAY'))
FROM YOUR_TABLE

当然,你可以在 SQL 中一并编写,我将其拆分只是为了更好的可见性。

请注意,对于 12 月 29 日至 1 月 3 日之间的日期,使用此方法时可能会得到意想不到的结果,因为一年可能有 52 或 53 周,而这些日期可能属于以前的日期。明年。

【讨论】:

    【解决方案4】:

    SQL Fiddle

    Oracle 11g R2 架构设置

    CREATE FUNCTION TO_ISO_WEEK_DATE(
      week        NUMBER,
      year        NUMBER
    ) RETURN DATE DETERMINISTIC
    IS
    BEGIN
      RETURN NEXT_DAY(
              TO_DATE( TO_CHAR( year, '0000' ) || '0104', 'YYYYMMDD' )
                - INTERVAL '7' DAY, 'MONDAY'
             )
             + ( week - 1 ) * 7;
    END TO_ISO_WEEK_DATE;
    /
    
    CREATE FUNCTION SAME_DAY_AND_WEEK_OF_YEAR(
      dt   DATE,
      year NUMBER
    ) RETURN DATE DETERMINISTIC
    IS
      p_week NUMBER(2,0) := TO_NUMBER( TO_CHAR( dt, 'IW' ) );
      p_day  VARCHAR2(9) := TO_CHAR( dt, 'DAY' );
    BEGIN
      RETURN NEXT_DAY( TO_ISO_WEEK_DATE( p_week, year ) - 1, p_day );
    END SAME_DAY_AND_WEEK_OF_YEAR;
    /
    

    查询 1

    SELECT TO_CHAR( SYSDATE + LEVEL - 1, 'YYYY-MM-DD (IW-D)' ) AS "Date 2015",
           TO_CHAR( SAME_DAY_AND_WEEK_OF_YEAR( SYSDATE + LEVEL - 1, 2014 ), 'YYYY-MM-DD (IW-D)' ) AS "Date 2014",
           TO_CHAR( SAME_DAY_AND_WEEK_OF_YEAR( SYSDATE + LEVEL - 1, 2013 ), 'YYYY-MM-DD (IW-D)' ) AS "Date 2013",
           TO_CHAR( SAME_DAY_AND_WEEK_OF_YEAR( SYSDATE + LEVEL - 1, 2012 ), 'YYYY-MM-DD (IW-D)' ) AS "Date 2012",
           TO_CHAR( SAME_DAY_AND_WEEK_OF_YEAR( SYSDATE + LEVEL - 1, 2011 ), 'YYYY-MM-DD (IW-D)' ) AS "Date 2011"
    FROM   DUAL
    CONNECT BY LEVEL <= 7
    

    Results

    |         Date 2015 |         Date 2014 |         Date 2013 |         Date 2012 |         Date 2011 |
    |-------------------|-------------------|-------------------|-------------------|-------------------|
    | 2015-06-12 (24-6) | 2014-06-13 (24-6) | 2013-06-14 (24-6) | 2012-06-15 (24-6) | 2011-06-17 (24-6) |
    | 2015-06-13 (24-7) | 2014-06-14 (24-7) | 2013-06-15 (24-7) | 2012-06-16 (24-7) | 2011-06-18 (24-7) |
    | 2015-06-14 (24-1) | 2014-06-15 (24-1) | 2013-06-16 (24-1) | 2012-06-17 (24-1) | 2011-06-19 (24-1) |
    | 2015-06-15 (25-2) | 2014-06-16 (25-2) | 2013-06-17 (25-2) | 2012-06-18 (25-2) | 2011-06-20 (25-2) |
    | 2015-06-16 (25-3) | 2014-06-17 (25-3) | 2013-06-18 (25-3) | 2012-06-19 (25-3) | 2011-06-21 (25-3) |
    | 2015-06-17 (25-4) | 2014-06-18 (25-4) | 2013-06-19 (25-4) | 2012-06-20 (25-4) | 2011-06-22 (25-4) |
    | 2015-06-18 (25-5) | 2014-06-19 (25-5) | 2013-06-20 (25-5) | 2012-06-21 (25-5) | 2011-06-23 (25-5) |
    

    【讨论】:

      【解决方案5】:

      不管是不是闰年,只要加上 364 例如

      select
      to_char(to_date('24/01/2016','dd/mm/yyyy'),'DAY DD/MM/YYYY') as CrossesLeapYear_PivotDate,
      to_char(add_months(to_date('24/01/2016','dd/mm/yyyy'),12), 'DAY DD/MM/YYYY') as CrossesLeapYear_NextYearDate,
      to_char(to_date('24/01/2016','dd/mm/yyyy') + 364, 'DAY DD/MM/YYYY') as CrossesLeapYear_SameNextYear,
      to_char(to_date('24/01/2017','dd/mm/yyyy'),'DAY DD/MM/YYYY') as NoLeapYear_PivotDate,
      to_char(add_months(to_date('24/01/2017','dd/mm/yyyy'),12), 'DAY DD/MM/YYYY') as NoLeapYear_NextYearDate,
      to_char(to_date('24/01/2017','dd/mm/yyyy') + 364, 'DAY DD/MM/YYYY') as NoLeapYear_SameNextYear
      from dual
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-24
        • 1970-01-01
        • 1970-01-01
        • 2019-11-11
        相关资源
        最近更新 更多