计算

时间:2016-02-10 18:12:28

标签: sql oracle

我有一个每周填充一次信息的表格,其中包含表格中作为单个列填充的日期。

我正在研究一个基本上比较本周数据与上周数据的查询,因此我需要知道上周哪一周。这很容易通过以下方式实现:

WHERE TO_CHAR(LASTWEEK.DATE_GENERATED, 'IW') = TO_CHAR(SYSDATE, 'IW') -1
  AND TO_CHAR(LASTWEEK.DATE_GENERATED, 'YY') = TO_CHAR(SYSDATE, 'YY')

该表可能包含多年的数据,因此我也检查年份是否相同。

问题出现在我们处于一年的第一周,我们想与前一周进行比较。通过这种方式,我们在第1周减去1它给我们0,但我希望它与上一年的第54周进行比较。

有没有办法实现这个目标?

我觉得TRUNC功能可能适用于此,但我不确定如何在这种情况下使用它,同时请记住它不应该与同年相比,而是去年。

提前致谢!

3 个答案:

答案 0 :(得分:6)

我完全避免在这个事件中使用TO_CHAR ...保持DATE格式...更安全,尤其是在违反年限时......

 where trunc(LASTWEEK.DATE_GENERATED,'IW') = trunc(sysdate-7,'IW')

单一条件应该给你:)

你可以看到它在这里做了什么:

    1  with w_data as (select sysdate-level d from dual connect by level <= 20 )
    2  select d, trunc(d, 'IW') w
    3* from w_data
  SQL> /

  D                    W
  -------------------- --------------------
  09-feb-2016 13:20:41 08-feb-2016 00:00:00
  08-feb-2016 13:20:41 08-feb-2016 00:00:00
  07-feb-2016 13:20:41 01-feb-2016 00:00:00
  06-feb-2016 13:20:41 01-feb-2016 00:00:00
  05-feb-2016 13:20:41 01-feb-2016 00:00:00
  04-feb-2016 13:20:41 01-feb-2016 00:00:00
  03-feb-2016 13:20:41 01-feb-2016 00:00:00
  02-feb-2016 13:20:41 01-feb-2016 00:00:00
  01-feb-2016 13:20:41 01-feb-2016 00:00:00
  31-jan-2016 13:20:41 25-jan-2016 00:00:00
  30-jan-2016 13:20:41 25-jan-2016 00:00:00
  29-jan-2016 13:20:41 25-jan-2016 00:00:00
  28-jan-2016 13:20:41 25-jan-2016 00:00:00
  27-jan-2016 13:20:41 25-jan-2016 00:00:00
  26-jan-2016 13:20:41 25-jan-2016 00:00:00
  25-jan-2016 13:20:41 25-jan-2016 00:00:00
  24-jan-2016 13:20:41 18-jan-2016 00:00:00
  23-jan-2016 13:20:41 18-jan-2016 00:00:00
  22-jan-2016 13:20:41 18-jan-2016 00:00:00
  21-jan-2016 13:20:41 18-jan-2016 00:00:00

  20 rows selected.

答案 1 :(得分:3)

您可以使用sysdate - 7与一周前的日期进行比较,并结合使用单个值:

WHERE TO_CHAR(LASTWEEK.DATE_GENERATED, 'IYYYIW') = TO_CHAR(SYSDATE - 7, 'IYYYIW')

注意我正在使用IYYY年份模型来匹配IW模型,否则你会得到奇怪的结果。

但是@ditto显示使用IW格式掩码的TRUNC更清晰。并且正如@MaxU所指出的,截断源列将阻止使用索引,除非您具有匹配的基于函数的索引。您可以通过稍微修改Ditto的方法来避免这种情况:

WHERE LASTWEEK.DATE_GENERATED >= TRUNC(SYSDATE - 7, 'IW')
AND LASTWEEK.DATE_GENERATED < TRUNC(SYSDATE, 'IW');

作为演示:

with lastweek(date_generated) as (
  select sysdate - level from dual connect by level <= 50
)
SELECT LASTWEEK.DATE_GENERATED
FROM LASTWEEK
WHERE LASTWEEK.DATE_GENERATED >= TRUNC(SYSDATE - 7, 'IW')
AND LASTWEEK.DATE_GENERATED < TRUNC(SYSDATE, 'IW');

DATE_GENERATED
--------------
2016-02-07    
2016-02-06    
2016-02-05    
2016-02-04    
2016-02-03    
2016-02-02    
2016-02-01    

或者看看年份的变化,让我们再回过头来看看,再次作为演示:

with lastweek(date_generated) as (
  select sysdate - level from dual connect by level <= 50
)
SELECT LASTWEEK.DATE_GENERATED
FROM LASTWEEK
WHERE LASTWEEK.DATE_GENERATED >= TRUNC(SYSDATE - 42, 'IW')
AND LASTWEEK.DATE_GENERATED < TRUNC(SYSDATE - 35, 'IW');

DATE_GENERATED
--------------
2016-01-03    
2016-01-02    
2016-01-01    
2015-12-31    
2015-12-30    
2015-12-29    
2015-12-28    

答案 2 :(得分:1)

来自Ditto的查询将起作用,但它不会使用“LASTWEEK.DATE_GENERATED”列上的索引,因为应用了函数(trunc),所以我会选择以下内容:

select
    next_day(to_date('2016-01-10','yyyy-mm-dd')-14, 'MONDAY'),
    next_day(to_date('2016-01-10','yyyy-mm-dd')-14, 'SUNDAY')
from dual;

输出:

12/28/2015        01/03/2016

所以你的查询是:

WHERE LASTWEEK.DATE_GENERATED
between next_day(to_date('2016-01-10','yyyy-mm-dd')-14, 'MONDAY')
and next_day(to_date('2016-01-10','yyyy-mm-dd')-14, 'SUNDAY')