我有一个每周填充一次信息的表格,其中包含表格中作为单个列填充的日期。
我正在研究一个基本上比较本周数据与上周数据的查询,因此我需要知道上周哪一周。这很容易通过以下方式实现:
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功能可能适用于此,但我不确定如何在这种情况下使用它,同时请记住它不应该与同年相比,而是去年。
提前致谢!
答案 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')